ActionItemService
in package
ActionItemService - lifecycle operations for the reusable to-do subsystem.
Owns materialization of action items from template-style definitions and the gated complete/reopen/cancel transitions (each writing an audit log row). All eligibility decisions delegate to ActionItemAssigneeResolver so "who can flip a check" is enforced consistently.
Table of Contents
Constants
- CASCADE_WARNING_DATA_KEY : mixed = 'cascadeWarning'
- COMPLETION_EVENT_FAILURE_REASON : mixed = 'Post-completion processing could not be finish...
- SYNCHRONIZATION_FAILURE_REASON : mixed = 'To-do workflow synchronization failed. Review...
- SYSTEM_AUTO_COMPLETION_NOTE : mixed = 'Completed automatically after required fields...
- SYSTEM_DEFINITION_SYNC_CANCEL_NOTE : mixed = 'Cancelled automatically because this to-do is...
- Persisted provenance marker matched exactly against action_item_logs.note.
- SYSTEM_DEFINITION_SYNC_REOPEN_NOTE : mixed = 'Reopened automatically because this to-do retu...
- SYSTEM_REQUIREMENT_REOPEN_NOTE : mixed = 'Reopened automatically after required fields w...
- TRANSITION_FAILURE_REASON : mixed = 'The to-do item could not be updated. Review th...
Properties
- $ActionItemLogs : ActionItemLogsTable
- $ActionItems : ActionItemsTable
- $resolver : ActionItemAssigneeResolver
Methods
- __construct() : mixed
- allGatingComplete() : bool
- Whether every gating item for an owner entity is completed.
- applyOpenCandidateScopeForMember() : SelectQuery
- Apply the open-item candidate SQL scope for a member.
- autoCompleteSatisfiedRequirements() : ServiceResult
- System-complete open required-field to-dos whose requirements are now satisfied, and reopen completed required-field to-dos whose requirements are no longer met.
- cancel() : ServiceResult
- Cancel an action item (e.g. when its owner entity is cancelled).
- complete() : ServiceResult
- Mark an action item completed, enforcing assignee eligibility.
- confirmationFor() : string
- Describe side effects before the user confirms an item transition.
- countOpenItemsForMember() : int
- Count open action items a member is eligible to act on.
- getActionableItemIdsForMember() : array<string|int, int>
- List the ids of open action items a member is eligible to act on.
- getItemsForEntity() : array<string|int, ActionItem>
- Fetch ordered action items for an owner entity.
- getOpenItemsForMember() : array<string|int, ActionItem>
- List open action items a member is eligible to act on.
- hasActiveGatingItems() : bool
- Whether an owner currently has any non-cancelled gating item.
- isMemberEligible() : bool
- Whether a member may act on (complete/reopen) a specific item.
- materializeFor() : ServiceResult
- Create action items for an owner entity from a list of definitions.
- ownerIsMutable() : bool
- Read-only lifecycle metadata shared by desktop, mobile, and plugin checklists.
- reopen() : ServiceResult
- Reopen a completed/cancelled action item, enforcing assignee eligibility.
- synchronizeFor() : ServiceResult
- Reconcile an owner's materialized action items with current definitions.
- syncRequiredFieldCompletionStates() : ServiceResult
- Synchronize required-field to-dos with their current requirement state.
- dispatchCompletedEvent() : void
- Announce a successful completion so consumers (e.g. the Awards plugin) can react without the core subsystem depending on them.
- transition() : ServiceResult
- Shared transition handler: validate, update status, write a log row.
- applyMemberCandidateScope() : void
- Narrow open-item queries to rows that could match the member's assignment scope.
- eligibilitySelectColumns() : array<string|int, string>
- Columns needed for PHP-side residual eligibility checks.
- getCurrentOfficeScopesForMember() : array<int, array<string|int, int>>
- isTransitionAllowed() : bool
- Validate lifecycle transitions after locking the latest persisted row.
- lockOwner() : EntityInterface|null
- Lock a persisted owner before its action item to keep cross-entity updates ordered.
- normalizeDefinitions() : ServiceResult
- Validate and normalize definition snapshots before any writes occur.
- ownerAllowsActionItemMutations() : bool
- Apply an owner's optional terminal-lifecycle contract.
- ownerReadOnlyReason() : string
- Explain stale requests using the owner's domain lifecycle.
- prepareCompletionRequirements() : ServiceResult
- Apply and validate provider-backed completion requirements.
- snapshotValuesEqual() : bool
- Whether two snapshot values are equivalent for synchronization purposes.
- syncRequiredFieldCompletionStatesForActiveOwner() : ServiceResult
- Reconcile required fields after the persisted owner has been locked.
- wasCancelledByDefinitionSync() : bool
- Check explicit cancellation provenance using the latest status log only.
Constants
CASCADE_WARNING_DATA_KEY
public
mixed
CASCADE_WARNING_DATA_KEY
= 'cascadeWarning'
COMPLETION_EVENT_FAILURE_REASON
public
mixed
COMPLETION_EVENT_FAILURE_REASON
= 'Post-completion processing could not be finished. Review the server logs for details.'
SYNCHRONIZATION_FAILURE_REASON
public
mixed
SYNCHRONIZATION_FAILURE_REASON
= 'To-do workflow synchronization failed. Review the server logs for details.'
SYSTEM_AUTO_COMPLETION_NOTE
public
mixed
SYSTEM_AUTO_COMPLETION_NOTE
= 'Completed automatically after required fields were satisfied.'
SYSTEM_DEFINITION_SYNC_CANCEL_NOTE
Persisted provenance marker matched exactly against action_item_logs.note.
public
mixed
SYSTEM_DEFINITION_SYNC_CANCEL_NOTE
= 'Cancelled automatically because this to-do is no longer in the current workflow definition.'
Do not reword without migrating existing log rows first.
SYSTEM_DEFINITION_SYNC_REOPEN_NOTE
public
mixed
SYSTEM_DEFINITION_SYNC_REOPEN_NOTE
= 'Reopened automatically because this to-do returned to the current workflow definition.'
SYSTEM_REQUIREMENT_REOPEN_NOTE
public
mixed
SYSTEM_REQUIREMENT_REOPEN_NOTE
= 'Reopened automatically after required fields were cleared.'
TRANSITION_FAILURE_REASON
public
mixed
TRANSITION_FAILURE_REASON
= 'The to-do item could not be updated. Review the server logs for details.'
Properties
$ActionItemLogs
protected
ActionItemLogsTable
$ActionItemLogs
$ActionItems
protected
ActionItemsTable
$ActionItems
$resolver
protected
ActionItemAssigneeResolver
$resolver
Methods
__construct()
public
__construct([ActionItemAssigneeResolver|null $resolver = null ]) : mixed
Parameters
- $resolver : ActionItemAssigneeResolver|null = null
-
Eligibility resolver
allGatingComplete()
Whether every gating item for an owner entity is completed.
public
allGatingComplete(string $entityType, int $entityId) : bool
Returns false when there are no gating items at all, so callers do not surface a "ready" action for entities that have no checklist yet.
Parameters
- $entityType : string
-
Polymorphic owner type
- $entityId : int
-
Owner primary key
Return values
boolapplyOpenCandidateScopeForMember()
Apply the open-item candidate SQL scope for a member.
public
applyOpenCandidateScopeForMember(SelectQuery $query, int $memberId) : SelectQuery
The scope uses denormalized assignee lookup columns plus the member's cached permission/role branch coverage so grid endpoints can page and sort in SQL instead of hydrating every open to-do into PHP first.
Parameters
- $query : SelectQuery
-
Query to scope.
- $memberId : int
-
Member ID.
Return values
SelectQueryautoCompleteSatisfiedRequirements()
System-complete open required-field to-dos whose requirements are now satisfied, and reopen completed required-field to-dos whose requirements are no longer met.
public
autoCompleteSatisfiedRequirements(string $entityType, int $entityId[, int|null $completedEventActorId = null ]) : ServiceResult
Parameters
- $entityType : string
-
Polymorphic owner type.
- $entityId : int
-
Owner primary key.
- $completedEventActorId : int|null = null
-
Member whose action caused the auto-close, if any.
Return values
ServiceResult —Data includes completed, reopened, and skipped counts.
cancel()
Cancel an action item (e.g. when its owner entity is cancelled).
public
cancel(int $actionItemId, int $actorId[, string|null $note = null ][, bool $enforceEligibility = true ]) : ServiceResult
Parameters
- $actionItemId : int
-
The item to cancel
- $actorId : int
-
The acting member id
- $note : string|null = null
-
Optional audit note
- $enforceEligibility : bool = true
-
When false, skips the eligibility gate
Return values
ServiceResultcomplete()
Mark an action item completed, enforcing assignee eligibility.
public
complete(int $actionItemId, int $actorId[, string|null $note = null ][, bool $enforceEligibility = true ][, array<string, mixed> $completionData = [] ][, KmpIdentityInterface|null $actorIdentity = null ]) : ServiceResult
Parameters
- $actionItemId : int
-
The item to complete
- $actorId : int
-
The acting member id
- $note : string|null = null
-
Optional audit note
- $enforceEligibility : bool = true
-
When false, skips the eligibility gate (admin/backfill use)
- $completionData : array<string, mixed> = []
-
Submitted provider-backed completion data
- $actorIdentity : KmpIdentityInterface|null = null
-
Current actor identity
Return values
ServiceResultconfirmationFor()
Describe side effects before the user confirms an item transition.
public
confirmationFor(ActionItem $item, string $operation) : string
Parameters
- $item : ActionItem
- $operation : string
Return values
stringcountOpenItemsForMember()
Count open action items a member is eligible to act on.
public
countOpenItemsForMember(int $memberId) : int
Uses the same eligibility resolver as the rich list, but avoids branch hydration and presentation ordering for navigation badges.
Parameters
- $memberId : int
-
The member id
Return values
intgetActionableItemIdsForMember()
List the ids of open action items a member is eligible to act on.
public
getActionableItemIdsForMember(int $memberId) : array<string|int, int>
Mirrors getOpenItemsForMember() but returns only ids, for use as a
pre-resolved IN (...) filter when building the My To-Dos grid query.
Parameters
- $memberId : int
-
The member id
Return values
array<string|int, int>getItemsForEntity()
Fetch ordered action items for an owner entity.
public
getItemsForEntity(string $entityType, int $entityId[, bool $includeCancelled = false ]) : array<string|int, ActionItem>
Parameters
- $entityType : string
-
Polymorphic owner type
- $entityId : int
-
Owner primary key
- $includeCancelled : bool = false
-
Whether to include cancelled items
Return values
array<string|int, ActionItem>getOpenItemsForMember()
List open action items a member is eligible to act on.
public
getOpenItemsForMember(int $memberId[, string|null $entityType = null ]) : array<string|int, ActionItem>
Parameters
- $memberId : int
-
The member id
- $entityType : string|null = null
-
Optional owner-type filter
Return values
array<string|int, ActionItem>hasActiveGatingItems()
Whether an owner currently has any non-cancelled gating item.
public
hasActiveGatingItems(string $entityType, int $entityId) : bool
Parameters
- $entityType : string
-
Polymorphic owner type.
- $entityId : int
-
Owner primary key.
Return values
boolisMemberEligible()
Whether a member may act on (complete/reopen) a specific item.
public
isMemberEligible(ActionItem $item, int $memberId) : bool
Thin passthrough to the assignee resolver so UI surfaces can decide which per-check controls to render without duplicating eligibility logic.
Parameters
- $item : ActionItem
-
The action item
- $memberId : int
-
The acting member id
Return values
boolmaterializeFor()
Create action items for an owner entity from a list of definitions.
public
materializeFor(string $entityType, int $entityId, array<int, array<string, mixed>> $definitions[, int|null $branchId = null ]) : ServiceResult
Each definition is an associative array with keys: title, description, assignee_type, assignee_config, is_gating, sort_order, source_ref, branch_id. Missing keys fall back to sensible defaults. Materialization is idempotent on (entity_type, entity_id, source_ref): an existing item with the same source_ref is skipped.
Parameters
- $entityType : string
-
Polymorphic owner type (e.g. Awards.Bestowals)
- $entityId : int
-
Owner primary key
- $definitions : array<int, array<string, mixed>>
-
Item definitions
- $branchId : int|null = null
-
Default branch scope for all items
Return values
ServiceResult —Data is the array of created ActionItem entities
ownerIsMutable()
Read-only lifecycle metadata shared by desktop, mobile, and plugin checklists.
public
ownerIsMutable(ActionItem $item) : bool
Parameters
- $item : ActionItem
Return values
boolreopen()
Reopen a completed/cancelled action item, enforcing assignee eligibility.
public
reopen(int $actionItemId, int $actorId[, string|null $note = null ][, bool $enforceEligibility = true ]) : ServiceResult
Parameters
- $actionItemId : int
-
The item to reopen
- $actorId : int
-
The acting member id
- $note : string|null = null
-
Optional audit note
- $enforceEligibility : bool = true
-
When false, skips the eligibility gate
Return values
ServiceResultsynchronizeFor()
Reconcile an owner's materialized action items with current definitions.
public
synchronizeFor(string $entityType, int $entityId, array<int, array<string, mixed>> $definitions[, int|null $branchId = null ][, int|null $actorId = null ]) : ServiceResult
Definitions are matched by their stable source_ref. Matching items keep their lifecycle state and completion audit while their mutable snapshot fields are refreshed. New definitions are created, removed definitions are cancelled, and only items whose latest transition was a definition sync cancellation are reopened when their source_ref returns.
Parameters
- $entityType : string
-
Polymorphic owner type.
- $entityId : int
-
Owner primary key.
- $definitions : array<int, array<string, mixed>>
-
Current item definitions.
- $branchId : int|null = null
-
Default branch scope for definitions without one.
- $actorId : int|null = null
-
Member initiating the synchronization, if any.
Return values
ServiceResult —Data contains mutation and required-field reconciliation counts.
syncRequiredFieldCompletionStates()
Synchronize required-field to-dos with their current requirement state.
public
syncRequiredFieldCompletionStates(string $entityType, int $entityId[, int|null $completedEventActorId = null ]) : ServiceResult
Parameters
- $entityType : string
-
Polymorphic owner type.
- $entityId : int
-
Owner primary key.
- $completedEventActorId : int|null = null
-
Member whose action caused the auto-close, if any.
Return values
ServiceResult —Data includes completed, reopened, and skipped counts.
dispatchCompletedEvent()
Announce a successful completion so consumers (e.g. the Awards plugin) can react without the core subsystem depending on them.
protected
dispatchCompletedEvent(ActionItem $item, int|null $actorId) : void
Dispatched on the global EventManager after the status change commits; listeners are best-effort and must not affect the transition result.
Parameters
- $item : ActionItem
-
The completed item.
- $actorId : int|null
-
Member who completed the item, or null when system-completed.
transition()
Shared transition handler: validate, update status, write a log row.
protected
transition(int $actionItemId, int|null $actorId, string $toStatus, string|null $note, bool $enforceEligibility[, array<string, mixed> $completionData = [] ][, KmpIdentityInterface|null $actorIdentity = null ][, int|null $completedEventActorId = null ][, bool $dispatchCompletionEvent = true ]) : ServiceResult
Parameters
- $actionItemId : int
-
The item id
- $actorId : int|null
-
The acting member id, or null for system transitions
- $toStatus : string
-
Target status
- $note : string|null
-
Optional audit note
- $enforceEligibility : bool
-
Whether to enforce the eligibility gate
- $completionData : array<string, mixed> = []
-
Submitted provider-backed completion data
- $actorIdentity : KmpIdentityInterface|null = null
-
Current actor identity
- $completedEventActorId : int|null = null
-
Alternate actor for completion listeners.
- $dispatchCompletionEvent : bool = true
-
Whether to dispatch immediately after commit.
Return values
ServiceResultapplyMemberCandidateScope()
Narrow open-item queries to rows that could match the member's assignment scope.
private
applyMemberCandidateScope(SelectQuery $query, int $memberId) : void
Parameters
- $query : SelectQuery
-
The query to scope.
- $memberId : int
-
The member id.
eligibilitySelectColumns()
Columns needed for PHP-side residual eligibility checks.
private
eligibilitySelectColumns() : array<string|int, string>
Return values
array<string|int, string>getCurrentOfficeScopesForMember()
private
getCurrentOfficeScopesForMember(int $memberId) : array<int, array<string|int, int>>
Parameters
- $memberId : int
-
Member ID.
Return values
array<int, array<string|int, int>>isTransitionAllowed()
Validate lifecycle transitions after locking the latest persisted row.
private
isTransitionAllowed(string $fromStatus, string $toStatus) : bool
Parameters
- $fromStatus : string
- $toStatus : string
Return values
boollockOwner()
Lock a persisted owner before its action item to keep cross-entity updates ordered.
private
lockOwner(string $entityType, int $entityId) : EntityInterface|null
Entity types that do not resolve to a table on this connection retain the existing item-only locking behavior.
Parameters
- $entityType : string
-
Polymorphic owner type.
- $entityId : int
-
Owner primary key.
Return values
EntityInterface|null —Locked owner, when resolvable.
normalizeDefinitions()
Validate and normalize definition snapshots before any writes occur.
private
normalizeDefinitions(array<int, array<string, mixed>> $definitions, int|null $branchId) : ServiceResult
Parameters
- $definitions : array<int, array<string, mixed>>
-
Raw definitions.
- $branchId : int|null
-
Default branch scope.
Return values
ServiceResult —Data is keyed by normalized source_ref.
ownerAllowsActionItemMutations()
Apply an owner's optional terminal-lifecycle contract.
private
ownerAllowsActionItemMutations(EntityInterface|null $owner, string $entityType) : bool
A missing row for an owner type that implements the contract means the owner was deleted, so it must not fall through to generic item behavior.
Parameters
- $owner : EntityInterface|null
-
Locked owner entity.
- $entityType : string
-
Polymorphic owner type.
Return values
boolownerReadOnlyReason()
Explain stale requests using the owner's domain lifecycle.
private
ownerReadOnlyReason(EntityInterface|null $owner) : string
Parameters
- $owner : EntityInterface|null
Return values
stringprepareCompletionRequirements()
Apply and validate provider-backed completion requirements.
private
prepareCompletionRequirements(ActionItem $item, array<string, mixed> $completionData, int|null $actorId, KmpIdentityInterface|null $actorIdentity) : ServiceResult
Parameters
- $item : ActionItem
-
Action item.
- $completionData : array<string, mixed>
-
Submitted provider data.
- $actorId : int|null
-
Acting member id, or null for system validation.
- $actorIdentity : KmpIdentityInterface|null
-
Current actor identity.
Return values
ServiceResultsnapshotValuesEqual()
Whether two snapshot values are equivalent for synchronization purposes.
private
snapshotValuesEqual(mixed $current, mixed $desired) : bool
Parameters
- $current : mixed
-
Persisted value.
- $desired : mixed
-
Current definition value.
Return values
boolsyncRequiredFieldCompletionStatesForActiveOwner()
Reconcile required fields after the persisted owner has been locked.
private
syncRequiredFieldCompletionStatesForActiveOwner(string $entityType, int $entityId, int|null $completedEventActorId, array<int, ActionItem> &$completedItems) : ServiceResult
Parameters
- $entityType : string
- $entityId : int
- $completedEventActorId : int|null
- $completedItems : array<int, ActionItem>
-
Deferred completed events.
Return values
ServiceResultwasCancelledByDefinitionSync()
Check explicit cancellation provenance using the latest status log only.
private
wasCancelledByDefinitionSync(int $actionItemId) : bool
Parameters
- $actionItemId : int
-
Action item ID.