Skip to content

Commit

Permalink
Merge pull request #82 from tarfin-labs/setting-machines-in-model-method
Browse files Browse the repository at this point in the history
Add support to set machines in a model using `machines()` method.
  • Loading branch information
deligoez authored Sep 4, 2024
2 parents 362ae18 + e8a1a58 commit f1f6ddf
Show file tree
Hide file tree
Showing 5 changed files with 101 additions and 15 deletions.
48 changes: 37 additions & 11 deletions src/Traits/HasMachines.php
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ trait HasMachines
*/
protected static function bootHasMachines(): void
{
static::creating(function (Model $model): void {
static::creating(static function (Model $model): void {
foreach ($model->getCasts() as $attribute => $cast) {
if (
!isset($model->attributes[$attribute]) &&
Expand All @@ -40,19 +40,20 @@ public function getAttribute($key)
{
$attribute = parent::getAttribute($key);

if (
property_exists($this, 'machines') &&
array_key_exists($key, $this->machines) &&
$this->shouldInitializeMachine()
) {
/** @var \Tarfinlabs\EventMachine\Actor\Machine $machineClass */
[$machineClass, $contextKey] = explode(':', $this->machines[$key]);
if ($this->shouldInitializeMachine() === true) {

$machine = $machineClass::create(state: $attribute);
$machine = $this->findMachine($key);

$machine->state->context->set($contextKey, $this);
if ($machine !== null) {
/** @var \Tarfinlabs\EventMachine\Actor\Machine $machineClass */
[$machineClass, $contextKey] = explode(':', $machine);

return $machine;
$machine = $machineClass::create(state: $attribute);

$machine->state->context->set($contextKey, $this);

return $machine;
}
}

return $attribute;
Expand All @@ -67,4 +68,29 @@ public function shouldInitializeMachine(): bool
{
return true;
}

/**
* Checks if the machine configuration exists for the given key
* either in the `machines` method or the `machines` property of the model.
*/
private function findMachine($key): ?string
{
if (method_exists($this, 'machines')) {
$machines = $this->machines();

if (array_key_exists($key, $machines)) {
return $machines[$key];
}
}

if (property_exists($this, 'machines')) {
$machines = $this->machines;

if (array_key_exists($key, $machines)) {
return $machines[$key];
}
}

return null;
}
}
22 changes: 18 additions & 4 deletions tests/HasMachinesTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,17 +5,31 @@
use Tarfinlabs\EventMachine\Actor\Machine;
use Tarfinlabs\EventMachine\Tests\Stubs\Models\ModelA;
use Tarfinlabs\EventMachine\Tests\Stubs\Machines\AbcMachine;
use Tarfinlabs\EventMachine\Tests\Stubs\Machines\ElevatorMachine;
use Tarfinlabs\EventMachine\Tests\Stubs\Machines\TrafficLights\TrafficLightsMachine;

it('it should return a machine', function (): void {
$machine = AbcMachine::create();
$machine->persist();
$abcMachine = AbcMachine::create();
$abcMachine->persist();

$trafficLightsMachine = TrafficLightsMachine::create();
$trafficLightsMachine->persist();

$elevatorMachine = ElevatorMachine::create();
$elevatorMachine->persist();

ModelA::create([
'abc_mre' => $machine->state->history->first()->root_event_id,
'abc_mre' => $abcMachine->state->history->first()->root_event_id,
'traffic_mre' => $trafficLightsMachine->state->history->first()->root_event_id,
'elevator_mre' => $elevatorMachine->state->history->first()->root_event_id,
]);

$modelA = ModelA::first();

expect($modelA->abc_mre)
expect($modelA->elevator_mre)
->toBeInstanceOf(Machine::class)
->and($modelA->abc_mre)
->toBeInstanceOf(Machine::class)
->and($modelA->traffic_mre)
->toBeInstanceOf(Machine::class);
});
35 changes: 35 additions & 0 deletions tests/Stubs/Machines/ElevatorMachine.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
<?php

declare(strict_types=1);

namespace Tarfinlabs\EventMachine\Tests\Stubs\Machines;

use Tarfinlabs\EventMachine\Actor\Machine;
use Tarfinlabs\EventMachine\Definition\MachineDefinition;

class ElevatorMachine extends Machine
{
public static function definition(): MachineDefinition
{
return MachineDefinition::define(config: [
'initial' => 'stateB',
'context' => [
'modelA' => null,
'value' => 4,
],
'states' => [
'stateA' => [
'on' => [
'EVENT' => 'stateB',
],
],
'stateB' => [
'on' => [
'@always' => 'stateC',
],
],
'stateC' => [],
],
]);
}
}
10 changes: 10 additions & 0 deletions tests/Stubs/Models/ModelA.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
use Tarfinlabs\EventMachine\Traits\HasMachines;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Tarfinlabs\EventMachine\Tests\Stubs\Machines\AbcMachine;
use Tarfinlabs\EventMachine\Tests\Stubs\Machines\ElevatorMachine;
use Tarfinlabs\EventMachine\Tests\Stubs\Machines\TrafficLights\TrafficLightsMachine;

/**
Expand All @@ -16,6 +17,7 @@
* @property string $value
* @property \Tarfinlabs\EventMachine\Actor\Machine $abc_mre
* @property \Tarfinlabs\EventMachine\Actor\Machine $traffic_mre
* @property \Tarfinlabs\EventMachine\Actor\Machine $elevator_mre
*/
class ModelA extends Model
{
Expand All @@ -26,6 +28,7 @@ class ModelA extends Model
'value',
'abc_mre',
'traffic_mre',
'elevator_mre',
];
protected array $machines = [
'abc_mre' => AbcMachine::class.':modelA',
Expand All @@ -34,4 +37,11 @@ class ModelA extends Model
'value' => 'string',
'traffic_mre' => TrafficLightsMachine::class.':modelA',
];

protected function machines(): array
{
return [
'elevator_mre' => ElevatorMachine::class.':modelA',
];
}
}
1 change: 1 addition & 0 deletions tests/TestCase.php
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ public function getEnvironmentSetUp($app): void
$table->string('value')->nullable();
$table->ulid('abc_mre')->nullable();
$table->ulid('traffic_mre')->nullable();
$table->ulid('elevator_mre')->nullable();
$table->timestamps();
});
}
Expand Down

0 comments on commit f1f6ddf

Please sign in to comment.