Skip to content

Commit

Permalink
Merge pull request #79 from tarfin-labs/WEB-5096-event-machine-state-…
Browse files Browse the repository at this point in the history
…machine-diagramlarini-otomatik-olusturabilmek

Web 5096 event machine state machine diagramlarini otomatik olusturabilmek
  • Loading branch information
frkcn authored Jul 8, 2024
2 parents d569dd3 + 2f88e72 commit 6b6c35b
Show file tree
Hide file tree
Showing 13 changed files with 178 additions and 31 deletions.
4 changes: 1 addition & 3 deletions src/Behavior/ActionBehavior.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,4 @@
* This abstract class extends the InvokableBehavior class. It provides a way to define action behaviors
* that can be invoked within a specific context.
*/
abstract class ActionBehavior extends InvokableBehavior
{
}
abstract class ActionBehavior extends InvokableBehavior {}
4 changes: 1 addition & 3 deletions src/Behavior/GuardBehavior.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,4 @@
* This is an abstract class that extends InvokableBehavior and provides the base structure for guard behavior classes.
* Guards are used in event-driven systems to determine whether an event should be allowed to proceed or not.
*/
abstract class GuardBehavior extends InvokableBehavior
{
}
abstract class GuardBehavior extends InvokableBehavior {}
4 changes: 1 addition & 3 deletions src/Behavior/ResultBehavior.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,4 @@

namespace Tarfinlabs\EventMachine\Behavior;

abstract class ResultBehavior extends InvokableBehavior
{
}
abstract class ResultBehavior extends InvokableBehavior {}
155 changes: 155 additions & 0 deletions src/Console/Commands/GenerateUmlCommand.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,155 @@
<?php

declare(strict_types=1);

namespace Tarfinlabs\EventMachine\Console\Commands;

use Illuminate\Console\Command;
use Illuminate\Support\Facades\File;
use Tarfinlabs\EventMachine\Definition\StateDefinition;

class GenerateUmlCommand extends Command
{
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'machine:uml {machine : The Machine path}';

/**
* The console command description.
*
* @var string
*/
protected $description = 'Generate machine uml';

private array $lines = [];
private array $colors = [];

/**
* Execute the console command.
*/
public function handle(): void
{
$machinePath = $this->argument('machine');

$machine = $machinePath::create();
$this->lines[] = '@startuml';
$this->lines[] = 'skinparam linetype polyline';
$this->lines[] = '
<style>
stateDiagram {
Linecolor cornflowerblue
LineThickness 2
FontStyle bold
FontName Helvetica Neue
arrow {
LineColor cornflowerblue
LineThickness 2
}
}
</style>
';

$this->lines[] = 'set namespaceSeparator none';

$this->addTransition(from: '[*]', to: $machine->definition->initialStateDefinition->id);
foreach ($machine->definition->stateDefinitions as $stateDefinition) {
if ($stateDefinition->stateDefinitions !== null) {
$this->colors[$stateDefinition->id] = '#'.substr(dechex(crc32($stateDefinition->id)), 0, 6);
}

$this->handleStateDefinition(stateDefinition: $stateDefinition);
}

foreach ($this->colors as $state => $color) {
$this->lines[] = "state {$state}";
}

$this->lines[] = '@enduml';

$filePath = str_replace(
'\\',
DIRECTORY_SEPARATOR,
$machinePath
);

File::put(base_path(dirname($filePath).'/'.$machine->definition->root->key.'-machine.puml'), implode("\r\n", $this->lines));
}

private function handleStateDefinition(StateDefinition $stateDefinition): void
{
if ($stateDefinition->stateDefinitions !== null) {
$this->lines[] = "state {$stateDefinition->id} {";
$this->addTransition(from: '[*]', to: $stateDefinition->initialStateDefinition->id);
foreach ($stateDefinition->stateDefinitions as $childStateDefinition) {
$this->colors[$childStateDefinition->id] = $this->colors[$stateDefinition->id];
$this->handleStateDefinition(stateDefinition: $childStateDefinition);
}
$this->lines[] = '}';
}

$this->handleTransitions(stateDefinition: $stateDefinition);

if (!in_array("{$stateDefinition->id} : {$stateDefinition->description}", $this->lines)) {
$this->lines[] = "{$stateDefinition->id} : {$stateDefinition->description}";
}
}

private function handleTransitions(StateDefinition $stateDefinition): void
{
foreach ($stateDefinition->entry as $entryAction) {
$this->lines[] = "{$stateDefinition->id} : {$entryAction}";
}

if ($stateDefinition->transitionDefinitions !== null) {
foreach ($stateDefinition->transitionDefinitions as $event => $transitionDefinition) {
$branches = $transitionDefinition->branches ?? [];
$eventName = str_replace('@', '', $event);

/** @var \Tarfinlabs\EventMachine\Definition\TransitionBranch $branch */
foreach ($branches as $branch) {

$this->addTransition(
from: $stateDefinition,
to: $branch->target,
eventName: $eventName,
);
}
}
}
}

private function addTransition(
StateDefinition|string $from,
StateDefinition|string|null $to,
?string $eventName = '',
string $direction = 'down',
array $attributes = [],
string $arrow = '-'
): void {

$from = $from->id ?? $from;
$to = $to?->id ?? $to ?? $from;

foreach ($this->colors as $id => $transitionColor) {
if (str_starts_with($to, $id)) {
$attributes[] = $transitionColor;
break;
}
}

$attributeString = '';
if (!empty($attributes)) {
$attributeString = '['.implode(',', $attributes).']';
}

if (empty($eventName)) {
$this->lines[] = "{$from} -{$attributeString}$direction$arrow> {$to}";
} else {
$this->lines[] = "{$from} -{$attributeString}$direction$arrow> {$to} : <color:green>[{$eventName}]</color>";
}
}
}
3 changes: 1 addition & 2 deletions src/ContextManager.php
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,7 @@ class ContextManager extends Data
public function __construct(
#[ArrayType]
public array|Optional $data = [],
) {
}
) {}

/**
* Get a value from the context by its key.
Expand Down
4 changes: 1 addition & 3 deletions src/EventCollection.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,4 @@

use Illuminate\Database\Eloquent\Collection;

class EventCollection extends Collection
{
}
class EventCollection extends Collection {}
4 changes: 1 addition & 3 deletions src/Exceptions/MachineContextValidationException.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,4 @@
/**
* Represents an exception thrown when the validation of the machine context fails.
*/
class MachineContextValidationException extends ValidationException
{
}
class MachineContextValidationException extends ValidationException {}
4 changes: 1 addition & 3 deletions src/Exceptions/MachineEventValidationException.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,4 @@
*
* This class represents an exception that is thrown when a validation error occurs while processing a machine event.
*/
class MachineEventValidationException extends ValidationException
{
}
class MachineEventValidationException extends ValidationException {}
4 changes: 1 addition & 3 deletions src/Exceptions/MachineValidationException.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,4 @@
* This exception is used to handle validation errors specific to the Machine class.
* It extends the ValidationException class to provide more specific functionality.
*/
class MachineValidationException extends ValidationException
{
}
class MachineValidationException extends ValidationException {}
4 changes: 3 additions & 1 deletion src/MachineServiceProvider.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

use Spatie\LaravelPackageTools\Package;
use Spatie\LaravelPackageTools\PackageServiceProvider;
use Tarfinlabs\EventMachine\Console\Commands\GenerateUmlCommand;

/**
* Class MachineServiceProvider.
Expand All @@ -31,6 +32,7 @@ public function configurePackage(Package $package): void
$package
->name('event-machine')
->hasConfigFile('machine')
->hasMigration('create_machine_events_table');
->hasMigration('create_machine_events_table')
->hasCommand(GenerateUmlCommand::class);
}
}
9 changes: 9 additions & 0 deletions tests/CommandTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
<?php

declare(strict_types=1);

use Tarfinlabs\EventMachine\Console\Commands\GenerateUmlCommand;

it('it has GenerateUmlCommand', function (): void {
$this->assertTrue(class_exists(GenerateUmlCommand::class));
});
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,5 @@

class DoNothingInsideClassAction extends ActionBehavior
{
public function __invoke(): void
{
}
public function __invoke(): void {}
}
6 changes: 2 additions & 4 deletions tests/Stubs/Machines/TrafficLights/TrafficLightsMachine.php
Original file line number Diff line number Diff line change
Expand Up @@ -58,10 +58,8 @@ public static function definition(): MachineDefinition
'DEX' => DecreaseEvent::class,
],
'actions' => [
'doNothingAction' => function (): void {
},
'doNothingAction2' => function (ContextManager $context, EventBehavior $eventBehavior): void {
},
'doNothingAction' => function (): void {},
'doNothingAction2' => function (ContextManager $context, EventBehavior $eventBehavior): void {},
'doNothingInsideClassAction' => DoNothingInsideClassAction::class,
],
],
Expand Down

0 comments on commit 6b6c35b

Please sign in to comment.