chore: update document approval workflow and bug fixes
This commit is contained in:
84
app/Traits/HasStateMachine.php
Normal file
84
app/Traits/HasStateMachine.php
Normal file
@@ -0,0 +1,84 @@
|
||||
<?php
|
||||
|
||||
namespace App\Traits;
|
||||
|
||||
use InvalidArgumentException;
|
||||
|
||||
/**
|
||||
* Custom state machine trait for Eloquent models.
|
||||
* Replacement for spatie/laravel-model-states (incompatible with Laravel 13).
|
||||
*
|
||||
* Usage:
|
||||
* 1. Define a PHP enum for your states
|
||||
* 2. Use this trait on your model
|
||||
* 3. Implement `getStateMachineConfig()` returning state field + allowed transitions
|
||||
*/
|
||||
trait HasStateMachine
|
||||
{
|
||||
/**
|
||||
* Get the state machine configuration.
|
||||
* Override in your model.
|
||||
*
|
||||
* @return array{field: string, transitions: array<string, string[]>}
|
||||
*/
|
||||
abstract protected static function stateMachineConfig(): array;
|
||||
|
||||
public function getStateField(): string
|
||||
{
|
||||
return static::stateMachineConfig()['field'];
|
||||
}
|
||||
|
||||
public function getCurrentState(): string
|
||||
{
|
||||
$field = $this->getStateField();
|
||||
return $this->{$field};
|
||||
}
|
||||
|
||||
public function canTransitionTo(string $newState): bool
|
||||
{
|
||||
$config = static::stateMachineConfig();
|
||||
$currentState = $this->getCurrentState();
|
||||
$transitions = $config['transitions'] ?? [];
|
||||
|
||||
if (!isset($transitions[$currentState])) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return in_array($newState, $transitions[$currentState], true);
|
||||
}
|
||||
|
||||
public function transitionTo(string $newState): static
|
||||
{
|
||||
if (!$this->canTransitionTo($newState)) {
|
||||
$currentState = $this->getCurrentState();
|
||||
$field = $this->getStateField();
|
||||
throw new InvalidArgumentException(
|
||||
"Cannot transition '{$field}' from '{$currentState}' to '{$newState}'."
|
||||
);
|
||||
}
|
||||
|
||||
$field = $this->getStateField();
|
||||
$oldState = $this->getCurrentState();
|
||||
|
||||
$this->{$field} = $newState;
|
||||
$this->save();
|
||||
|
||||
// Fire an event for the transition
|
||||
$modelName = class_basename(static::class);
|
||||
event("{$modelName}StateChanged", [
|
||||
'model' => $this,
|
||||
'field' => $field,
|
||||
'from' => $oldState,
|
||||
'to' => $newState,
|
||||
]);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getAllowedTransitions(): array
|
||||
{
|
||||
$config = static::stateMachineConfig();
|
||||
$currentState = $this->getCurrentState();
|
||||
return $config['transitions'][$currentState] ?? [];
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user