class Modification extends Model (View source)

A change to a model: an audit row if it was saved directly, or a request if it's waiting for approval.

Holds the change as a diff in modifications, and its votes in approvals and disapprovals.

Constants

FLOW_DIRECT

An audit row for a change that was saved directly.

FLOW_APPROVAL

A change held for approval.

STATUS_APPLIED

Status of a direct audit row.

STATUS_PENDING

Waiting for a decision.

STATUS_APPROVED

Approved, and applied unless the model has updateWhenApproved off.

STATUS_REJECTED

Rejected. This is final: send the change again to retry it.

STATUS_PARTIALLY_RESOLVED

Its items are decided, some approved and some rejected.

Properties

protected $table
protected $guarded
string|null $modifiable_type
int|null $modifiable_id

Null until a deferred creation is approved.

string|null $modifier_type
int|null $modifier_id
string|null $flow

One of the FLOW_ constants.

string|null $status

One of the STATUS_ constants.

string|null $event_type
string|null $operation_id
bool $is_update

False for a creation.

bool $active

Legacy flag, derived from flow and status.

bool $is_modification

Legacy flag, derived from flow and status.

int $approvers_required
int $disapprovers_required
string $md5

Identifies an identical pending change.

ArrayObject $modifications

The diff, keyed by attribute.

ArrayObject|null $meta
ArrayObject|null $context
Carbon|null $occurred_at

When the change was requested or saved.

int read-only $approvers_remaining
int read-only $disapprovers_remaining

Methods

array
casts()

No description

static void
booted()

No description

MorphTo
modifiable()

The model this change belongs to.

MorphTo
modifier()

The model recorded as the author of the change.

HasMany
approvals()

The approvals cast on this modification and on its items.

HasMany
disapprovals()

The disapprovals cast on this modification and on its items.

HasMany
items()

The separately decidable parts of this change, if the model defines any.

int
getApproversRemainingAttribute()

Approvals still missing, read as approvers_remaining. Votes on items don't count.

int
getDisapproversRemainingAttribute()

Disapprovals still missing, read as disapprovers_remaining. Votes on items don't count.

int
getApprovalsRemainingAttribute() deprecated

No description

int
getDisapprovalsRemainingAttribute() deprecated

No description

bool
isPending()

Whether this row is still waiting for a decision. Anything else, including a direct audit row, can't take a vote: applying it again would overwrite whatever changed since.

bool
isCreation()

Whether this requests or records a new row, not a change to an existing one.

string
modifiableClass()

The modifiable class, resolving a morph alias.

Model|null
modifiableWithDrafts()

The modifiable, including a row hidden while its creation waits for approval, which the modifiable relation can't see.

void
forceApprovalUpdate()

Skips the votes, not the rules: only a pending change can be forced, and a rejected item stays rejected. Anything else would overwrite whatever changed since it was decided.

void
forceApprovalCreate()

forceApprovalUpdate() for a creation, refusing anything else: a query that went wrong must not apply a change to an existing row under this name.

void
syncLegacyFlags()

Derives the legacy active/is_modification booleans from flow/ status, so old consumers reading those columns keep working without changes: direct/applied => inactive audit row; approval/pending => active pending row; approval/approved|rejected|partially_resolved => inactive, resolved row.

string
recalculateStatusFromItems()

Recomputes this modification's status from its items' statuses.

Builder
scopeActiveOnly(Builder $query)

Only the rows flagged active, which are the pending ones.

Builder
scopeInactiveOnly(Builder $query)

Only the rows not flagged active: audit rows and decided changes.

Builder
scopeChanges(Builder $query)

Only changes to existing rows.

Builder
scopeCreations(Builder $query)

Only creations.

Details

protected array casts()

No description

Return Value

array

static protected void booted()

No description

Return Value

void

MorphTo modifiable()

The model this change belongs to.

Hides rows waiting for approval. Use modifiableWithDrafts() to reach them.

Return Value

MorphTo

MorphTo modifier()

The model recorded as the author of the change.

Return Value

MorphTo

HasMany approvals()

The approvals cast on this modification and on its items.

Return Value

HasMany

HasMany disapprovals()

The disapprovals cast on this modification and on its items.

Return Value

HasMany

HasMany items()

The separately decidable parts of this change, if the model defines any.

Return Value

HasMany

int getApproversRemainingAttribute()

Approvals still missing, read as approvers_remaining. Votes on items don't count.

Return Value

int

int getDisapproversRemainingAttribute()

Disapprovals still missing, read as disapprovers_remaining. Votes on items don't count.

Return Value

int

int getApprovalsRemainingAttribute() deprecated

deprecated alias of approvers_remaining

No description

Return Value

int

int getDisapprovalsRemainingAttribute() deprecated

deprecated alias of disapprovers_remaining

No description

Return Value

int

bool isPending()

Whether this row is still waiting for a decision. Anything else, including a direct audit row, can't take a vote: applying it again would overwrite whatever changed since.

Return Value

bool

bool isCreation()

Whether this requests or records a new row, not a change to an existing one.

Return Value

bool

string modifiableClass()

The modifiable class, resolving a morph alias.

Return Value

string

Model|null modifiableWithDrafts()

The modifiable, including a row hidden while its creation waits for approval, which the modifiable relation can't see.

Return Value

Model|null

void forceApprovalUpdate()

Skips the votes, not the rules: only a pending change can be forced, and a rejected item stays rejected. Anything else would overwrite whatever changed since it was decided.

All or nothing: a listener vetoing part of it leaves everything pending.

Return Value

void

void forceApprovalCreate()

forceApprovalUpdate() for a creation, refusing anything else: a query that went wrong must not apply a change to an existing row under this name.

Return Value

void

void syncLegacyFlags()

Derives the legacy active/is_modification booleans from flow/ status, so old consumers reading those columns keep working without changes: direct/applied => inactive audit row; approval/pending => active pending row; approval/approved|rejected|partially_resolved => inactive, resolved row.

Return Value

void

string recalculateStatusFromItems()

Recomputes this modification's status from its items' statuses.

No-op (returns the current status) when there are no items, since a Modification without items is decided as a whole by approve()/disapprove().

Return Value

string

Builder scopeActiveOnly(Builder $query)

Only the rows flagged active, which are the pending ones.

Parameters

Builder $query

Return Value

Builder

Builder scopeInactiveOnly(Builder $query)

Only the rows not flagged active: audit rows and decided changes.

Parameters

Builder $query

Return Value

Builder

Builder scopeChanges(Builder $query)

Only changes to existing rows.

Parameters

Builder $query

Return Value

Builder

Builder scopeCreations(Builder $query)

Only creations.

Parameters

Builder $query

Return Value

Builder