Skip to content

Commit

Permalink
Merge pull request #238 from fmeccanici/feature/allow-all-state-trans…
Browse files Browse the repository at this point in the history
…itions

Feature/Method to allow all state transitions
  • Loading branch information
freekmurze authored Sep 27, 2023
2 parents c4390cc + ee60dd7 commit f47e216
Show file tree
Hide file tree
Showing 13 changed files with 173 additions and 1 deletion.
17 changes: 16 additions & 1 deletion docs/working-with-transitions/01-configuring-transitions.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,22 @@ abstract class PaymentState extends State
}
```

In this example we're using both a simple transition, and a custom one. Transitions can be used like so:
In this example we're using both a simple transition, and a custom one. You can also allow all transitions if your states are already properly registered:

```php
abstract class PaymentState extends State
{
// …

public static function config(): StateConfig
{
return parent::config()
->allowAllTransitions();
}
}
```

Transitions can then be used like so:

```php
$payment->state->transitionTo(Paid::class);
Expand Down
14 changes: 14 additions & 0 deletions src/StateConfig.php
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,20 @@ public function stateChangedEvent(string $event): StateConfig
return $this;
}

/**
* @throws InvalidConfig
*/
public function allowAllTransitions(): StateConfig
{
if (empty($this->registeredStates)) {
throw new InvalidConfig('No states registered for ' . $this->baseStateClass);
}

$this->allowTransitions(collect($this->registeredStates)->crossJoin($this->registeredStates)->toArray());

return $this;
}

/**
* @param string|\Spatie\ModelStates\State $from
* @param string|\Spatie\ModelStates\State $to
Expand Down
19 changes: 19 additions & 0 deletions tests/Dummy/AllowAllTransitionsState/AllowAllTransitionsState.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
<?php

namespace Spatie\ModelStates\Tests\Dummy\AllowAllTransitionsState;

use Spatie\ModelStates\State;
use Spatie\ModelStates\StateConfig;

abstract class AllowAllTransitionsState extends State
{
public static function config(): StateConfig
{
return parent::config()
->default(StateA::class)
->registerState(StateA::class)
->registerState(StateB::class)
->registerState(StateC::class)
->allowAllTransitions();
}
}
8 changes: 8 additions & 0 deletions tests/Dummy/AllowAllTransitionsState/StateA.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
<?php

namespace Spatie\ModelStates\Tests\Dummy\AllowAllTransitionsState;

class StateA extends AllowAllTransitionsState
{

}
10 changes: 10 additions & 0 deletions tests/Dummy/AllowAllTransitionsState/StateB.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
<?php

namespace Spatie\ModelStates\Tests\Dummy\AllowAllTransitionsState;

use Spatie\ModelStates\Tests\Dummy\AllowAllTransitionsState\AllowAllTransitionsState;

class StateB extends AllowAllTransitionsState
{

}
10 changes: 10 additions & 0 deletions tests/Dummy/AllowAllTransitionsState/StateC.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
<?php

namespace Spatie\ModelStates\Tests\Dummy\AllowAllTransitionsState;

use Spatie\ModelStates\Tests\Dummy\AllowAllTransitionsState\AllowAllTransitionsState;

class StateC extends AllowAllTransitionsState
{

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
<?php

namespace Spatie\ModelStates\Tests\Dummy\AllowAllTransitionsStateWithNoRegisteredStates;

use Spatie\ModelStates\State;
use Spatie\ModelStates\StateConfig;

abstract class AllowAllTransitionsStateWithNoRegisteredStates extends State
{
public static function config(): StateConfig
{
return parent::config()
->default(StateAWithNoRegisteredStates::class)
->allowAllTransitions();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
<?php

namespace Spatie\ModelStates\Tests\Dummy\AllowAllTransitionsStateWithNoRegisteredStates;

class StateAWithNoRegisteredStates extends AllowAllTransitionsStateWithNoRegisteredStates
{

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
<?php

namespace Spatie\ModelStates\Tests\Dummy\AllowAllTransitionsStateWithNoRegisteredStates;

class StateBWithNoRegisteredStates extends AllowAllTransitionsStateWithNoRegisteredStates
{

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
<?php

namespace Spatie\ModelStates\Tests\Dummy\AllowAllTransitionsStateWithNoRegisteredStates;

class StateCWithNoRegisteredStates extends AllowAllTransitionsStateWithNoRegisteredStates
{

}
12 changes: 12 additions & 0 deletions tests/Dummy/TestModelAllowAllTransitions.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
<?php

namespace Spatie\ModelStates\Tests\Dummy;

use Spatie\ModelStates\Tests\Dummy\AllowAllTransitionsState\AllowAllTransitionsState;

class TestModelAllowAllTransitions extends TestModel
{
protected $casts = [
'state' => AllowAllTransitionsState::class,
];
}
12 changes: 12 additions & 0 deletions tests/Dummy/TestModelAllowAllTransitionsWithNoRegisteredStates.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
<?php

namespace Spatie\ModelStates\Tests\Dummy;

use Spatie\ModelStates\Tests\Dummy\AllowAllTransitionsStateWithNoRegisteredStates\AllowAllTransitionsStateWithNoRegisteredStates;

class TestModelAllowAllTransitionsWithNoRegisteredStates extends TestModel
{
protected $casts = [
'state' => AllowAllTransitionsStateWithNoRegisteredStates::class,
];
}
32 changes: 32 additions & 0 deletions tests/StateTest.php
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
<?php

use Illuminate\Support\Facades\Event;
use Spatie\ModelStates\Exceptions\InvalidConfig;
use Spatie\ModelStates\Tests\Dummy\AllowAllTransitionsStateWithNoRegisteredStates\AllowAllTransitionsStateWithNoRegisteredStates;
use Spatie\ModelStates\Events\StateChanged;
use Spatie\ModelStates\Exceptions\ClassDoesNotExtendBaseClass;
use Spatie\ModelStates\Tests\Dummy\CustomEventModelState\CustomEventModelStateB;
Expand All @@ -19,6 +21,8 @@
use Spatie\ModelStates\Tests\Dummy\OtherModelStates\StateX;
use Spatie\ModelStates\Tests\Dummy\OtherModelStates\StateY;
use Spatie\ModelStates\Tests\Dummy\TestModel;
use Spatie\ModelStates\Tests\Dummy\TestModelAllowAllTransitions;
use Spatie\ModelStates\Tests\Dummy\TestModelAllowAllTransitionsWithNoRegisteredStates;
use Spatie\ModelStates\Tests\Dummy\TestModelCustomEvent;
use Spatie\ModelStates\Tests\Dummy\TestModelCustomInvalidEvent;
use Spatie\ModelStates\Tests\Dummy\TestModelUpdatingEvent;
Expand Down Expand Up @@ -247,3 +251,31 @@

$model->state->transitionTo(CustomInvalidEventModelStateB::class);
});

it('should allow all transitions', function () {
$model = TestModelAllowAllTransitions::create();

expect($model->state->canTransitionTo(\Spatie\ModelStates\Tests\Dummy\AllowAllTransitionsState\StateA::class))->toBeTrue()
->and($model->state->canTransitionTo(\Spatie\ModelStates\Tests\Dummy\AllowAllTransitionsState\StateB::class))->toBeTrue()
->and($model->state->canTransitionTo(\Spatie\ModelStates\Tests\Dummy\AllowAllTransitionsState\StateC::class))->toBeTrue();

$model->state->transitionTo(\Spatie\ModelStates\Tests\Dummy\AllowAllTransitionsState\StateB::class);

expect($model->state->canTransitionTo(\Spatie\ModelStates\Tests\Dummy\AllowAllTransitionsState\StateA::class))->toBeTrue()
->and($model->state->canTransitionTo(\Spatie\ModelStates\Tests\Dummy\AllowAllTransitionsState\StateB::class))->toBeTrue()
->and($model->state->canTransitionTo(\Spatie\ModelStates\Tests\Dummy\AllowAllTransitionsState\StateC::class))->toBeTrue();

$model->state->transitionTo(\Spatie\ModelStates\Tests\Dummy\AllowAllTransitionsState\StateC::class);

expect($model->state->canTransitionTo(\Spatie\ModelStates\Tests\Dummy\AllowAllTransitionsState\StateA::class))->toBeTrue()
->and($model->state->canTransitionTo(\Spatie\ModelStates\Tests\Dummy\AllowAllTransitionsState\StateB::class))->toBeTrue()
->and($model->state->canTransitionTo(\Spatie\ModelStates\Tests\Dummy\AllowAllTransitionsState\StateC::class))->toBeTrue();

});

it('should throw exception when allowing all transitions when there are no registered states', function () {
$this->expectException(InvalidConfig::class);
$this->expectExceptionMessage('No states registered for ' . AllowAllTransitionsStateWithNoRegisteredStates::class);

TestModelAllowAllTransitionsWithNoRegisteredStates::create();
});

0 comments on commit f47e216

Please sign in to comment.