Skip to content

Commit

Permalink
Replace HasStateManager::generateMermaidGraphAsString with MermaidSta…
Browse files Browse the repository at this point in the history
…teConfigValidator
  • Loading branch information
spawnia committed Nov 11, 2024
1 parent 7078ba1 commit 19f4a62
Show file tree
Hide file tree
Showing 4 changed files with 81 additions and 50 deletions.
8 changes: 8 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,14 @@ See [GitHub releases](https://github.com/mll-lab/laravel-utils/releases).

## Unreleased

### Added

- Add `MLL\LaravelUtils\ModelStates\MermaidStateConfigValidator`

### Removed

- Remove `MLL\LaravelUtils\ModelStates\HasStateManager::generateMermaidGraphAsString`

## v6.0.0

### Changed
Expand Down
41 changes: 0 additions & 41 deletions src/ModelStates/HasStateManager.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,6 @@
namespace MLL\LaravelUtils\ModelStates;

use Illuminate\Database\Eloquent\Relations\MorphOne;
use JBZoo\MermaidPHP\Graph;
use JBZoo\MermaidPHP\Link;
use JBZoo\MermaidPHP\Node;
use MLL\LaravelUtils\ModelStates\Exceptions\UnknownStateException;

trait HasStateManager
Expand Down Expand Up @@ -63,44 +60,6 @@ public function stateManager(): MorphOne
);
}

public function generateMermaidGraphAsString(): string
{
$config = $this->stateClassConfig();

$graph = (new Graph(['abc_order' => true]))
->addStyle('linkStyle default interpolate basis');

$possibleStateInstances = array_map(
static fn (string $stateClass): State => new $stateClass(),
$config->possibleStates(),
);

foreach ($possibleStateInstances as $state) {
$graph->addNode(new Node($state::name()));
}

foreach ($possibleStateInstances as $state) {
foreach ($config->possibleNextStates($state) as $possibleNextState) {
$sourceNode = $graph->getNode($state::name());
$targetNode = $graph->getNode($possibleNextState::name());

if ($sourceNode instanceof Node && $targetNode instanceof Node) {
$transition = $config->transition($state::class, $possibleNextState::class);
assert($transition !== null);

$reflectionClass = new \ReflectionClass($transition);
$transitionName = $reflectionClass->getName() === DefaultTransition::class
? ''
: $reflectionClass->getShortName();

$graph->addLink(new Link($sourceNode, $targetNode, $transitionName));
}
}
}

return $graph->__toString();
}

public function stateClassConfig(): StateConfig
{
return $this->stateClass()::config();
Expand Down
66 changes: 66 additions & 0 deletions src/ModelStates/MermaidStateConfigValidator.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
<?php declare(strict_types=1);

namespace MLL\LaravelUtils\ModelStates;

use JBZoo\MermaidPHP\Graph;
use JBZoo\MermaidPHP\Link;
use JBZoo\MermaidPHP\Node;
use PHPUnit\Framework\Assert;

/** Requires the package jbzoo/mermaid-php. */
class MermaidStateConfigValidator
{
/** Performs a PHPUnit assertion that a generated Mermaid graph equals an expected result. */
public static function assertGraphEquals(string $expectedGraphString, Graph $actualGraph): void
{
Assert::assertSame(
expected: $expectedGraphString,
actual: $actualGraph->__toString(),
message: "The Mermaid graph did not match. See the actual generated graph at {$actualGraph->getLiveEditorUrl()}."
);
}

public static function assertStateConfigEquals(string $expectedGraphString, StateConfig $actualStateConfig): void
{
self::assertGraphEquals(
expectedGraphString: $expectedGraphString,
actualGraph: self::graphFromStateConfig($actualStateConfig),
);
}

public static function graphFromStateConfig(StateConfig $stateConfig): Graph
{
$graph = (new Graph(['abc_order' => true]))
->addStyle('linkStyle default interpolate basis');

$possibleStateInstances = array_map(
static fn (string $stateClass): State => new $stateClass(),
$stateConfig->possibleStates(),
);

foreach ($possibleStateInstances as $state) {
$graph->addNode(new Node($state::name()));
}

foreach ($possibleStateInstances as $state) {
foreach ($stateConfig->possibleNextStates($state) as $possibleNextState) {
$sourceNode = $graph->getNode($state::name());
$targetNode = $graph->getNode($possibleNextState::name());

if ($sourceNode instanceof Node && $targetNode instanceof Node) {
$transition = $stateConfig->transition($state::class, $possibleNextState::class);
assert($transition !== null);

$reflectionClass = new \ReflectionClass($transition);
$transitionName = $reflectionClass->getName() === DefaultTransition::class
? ''
: $reflectionClass->getShortName();

$graph->addLink(new Link($sourceNode, $targetNode, $transitionName));
}
}
}

return $graph;
}
}
16 changes: 7 additions & 9 deletions tests/ModelStates/StateTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

namespace MLL\LaravelUtils\Tests\ModelStates;

use App\ModelStates\ModelStates\ModelState;
use App\ModelStates\ModelStates\StateA;
use App\ModelStates\ModelStates\StateB;
use App\ModelStates\ModelStates\StateC;
Expand All @@ -18,6 +19,7 @@
use MLL\LaravelUtils\ModelStates\Exceptions\TransitionNotAllowed;
use MLL\LaravelUtils\ModelStates\Exceptions\TransitionNotFound;
use MLL\LaravelUtils\ModelStates\Exceptions\UnknownStateException;
use MLL\LaravelUtils\ModelStates\MermaidStateConfigValidator;
use MLL\LaravelUtils\ModelStates\TransitionDirection;
use MLL\LaravelUtils\Tests\DBTestCase;

Expand Down Expand Up @@ -182,9 +184,8 @@ public function testUnknownStateThrowsExceptionsForRetrieval(): void

public function testGenerateMermaidGraph(): void
{
$model = new TestModel();

$workflowAsMermaidGraph = 'graph TB;
$workflowAsMermaidGraph = /** @lang Mermaid */ <<<'MERMAID'
graph TB;
FOO_BAR("FOO_BAR");
STATE_A("STATE_A");
STATE_C("STATE_C");
Expand All @@ -195,12 +196,9 @@ public function testGenerateMermaidGraph(): void
STATE_A-->STATE_C;
STATE_A-->STATE_D;
linkStyle default interpolate basis;';
linkStyle default interpolate basis;
MERMAID;

self::assertSame(
$workflowAsMermaidGraph,
$model->generateMermaidGraphAsString(),
'Use https://mermaid.live/ for debugging.'
);
MermaidStateConfigValidator::assertStateConfigEquals($workflowAsMermaidGraph, ModelState::config());
}
}

0 comments on commit 19f4a62

Please sign in to comment.