[Workflow] Add colors to workflow dumps

This commit is contained in:
Alexis Lefebvre 2018-12-09 18:01:32 +01:00 committed by Fabien Potencier
parent 50ff35f1d7
commit 60ad109533
13 changed files with 286 additions and 86 deletions

View File

@ -6,6 +6,19 @@ CHANGELOG
* Trigger `entered` event for subject entering in the Workflow for the first time
* Added a context to `Workflow::apply()`. The `MethodMarkingStore` could be used to leverage this feature.
* Add style to transitions by declaring metadata:
```
$places = range('a', 'b');
$transition = new Transition('t1', 'a', 'b');
$transitions[] = $transition;
$transitionsMetadata = new \SplObjectStorage();
$transitionsMetadata[$transition] = [
'color' => 'Red',
'arrow_color' => '#00ff00',
];
$inMemoryMetadataStore = new InMemoryMetadataStore([], [], $transitionsMetadata);
return new Definition($places, $transitions, null, $inMemoryMetadataStore);
```
4.1.0
-----

View File

@ -63,6 +63,8 @@ class GraphvizDumper implements DumperInterface
*/
protected function findPlaces(Definition $definition, Marking $marking = null)
{
$workflowMetadata = $definition->getMetadataStore();
$places = [];
foreach ($definition->getPlaces() as $place) {
@ -74,6 +76,15 @@ class GraphvizDumper implements DumperInterface
$attributes['color'] = '#FF0000';
$attributes['shape'] = 'doublecircle';
}
$backgroundColor = $workflowMetadata->getMetadata('bg_color', $place);
if (null !== $backgroundColor) {
$attributes['style'] = 'filled';
$attributes['fillcolor'] = $backgroundColor;
}
$label = $workflowMetadata->getMetadata('label', $place);
if (null !== $label) {
$attributes['name'] = $label;
}
$places[$place] = [
'attributes' => $attributes,
];
@ -87,12 +98,23 @@ class GraphvizDumper implements DumperInterface
*/
protected function findTransitions(Definition $definition)
{
$workflowMetadata = $definition->getMetadataStore();
$transitions = [];
foreach ($definition->getTransitions() as $transition) {
$attributes = ['shape' => 'box', 'regular' => true];
$backgroundColor = $workflowMetadata->getMetadata('bg_color', $transition);
if (null !== $backgroundColor) {
$attributes['style'] = 'filled';
$attributes['fillcolor'] = $backgroundColor;
}
$name = $workflowMetadata->getMetadata('label', $transition) ?? $transition->getName();
$transitions[] = [
'attributes' => ['shape' => 'box', 'regular' => true],
'name' => $transition->getName(),
'attributes' => $attributes,
'name' => $name,
];
}
@ -107,7 +129,14 @@ class GraphvizDumper implements DumperInterface
$code = '';
foreach ($places as $id => $place) {
$code .= sprintf(" place_%s [label=\"%s\", shape=circle%s];\n", $this->dotize($id), $this->escape($id), $this->addAttributes($place['attributes']));
if (isset($place['attributes']['name'])) {
$placeName = $place['attributes']['name'];
unset($place['attributes']['name']);
} else {
$placeName = $id;
}
$code .= sprintf(" place_%s [label=\"%s\", shape=circle%s];\n", $this->dotize($id), $this->escape($placeName), $this->addAttributes($place['attributes']));
}
return $code;
@ -121,7 +150,7 @@ class GraphvizDumper implements DumperInterface
$code = '';
foreach ($transitions as $place) {
$code .= sprintf(" transition_%s [label=\"%s\", shape=box%s];\n", $this->dotize($place['name']), $this->escape($place['name']), $this->addAttributes($place['attributes']));
$code .= sprintf(" transition_%s [label=\"%s\",%s];\n", $this->dotize($place['name']), $this->escape($place['name']), $this->addAttributes($place['attributes']));
}
return $code;
@ -132,19 +161,23 @@ class GraphvizDumper implements DumperInterface
*/
protected function findEdges(Definition $definition)
{
$workflowMetadata = $definition->getMetadataStore();
$dotEdges = [];
foreach ($definition->getTransitions() as $transition) {
$transitionName = $workflowMetadata->getMetadata('label', $transition) ?? $transition->getName();
foreach ($transition->getFroms() as $from) {
$dotEdges[] = [
'from' => $from,
'to' => $transition->getName(),
'to' => $transitionName,
'direction' => 'from',
];
}
foreach ($transition->getTos() as $to) {
$dotEdges[] = [
'from' => $transition->getName(),
'from' => $transitionName,
'to' => $to,
'direction' => 'to',
];
@ -209,7 +242,7 @@ class GraphvizDumper implements DumperInterface
return \is_bool($value) ? ($value ? '1' : '0') : \addslashes($value);
}
private function addAttributes(array $attributes): string
protected function addAttributes(array $attributes): string
{
$code = [];
@ -217,7 +250,7 @@ class GraphvizDumper implements DumperInterface
$code[] = sprintf('%s="%s"', $k, $this->escape($v));
}
return $code ? ', '.implode(', ', $code) : '';
return $code ? ' '.implode(' ', $code) : '';
}
private function addOptions(array $options): string

View File

@ -14,6 +14,8 @@ namespace Symfony\Component\Workflow\Dumper;
use InvalidArgumentException;
use Symfony\Component\Workflow\Definition;
use Symfony\Component\Workflow\Marking;
use Symfony\Component\Workflow\Metadata\MetadataStoreInterface;
use Symfony\Component\Workflow\Transition;
/**
* PlantUmlDumper dumps a workflow as a PlantUML file.
@ -63,13 +65,13 @@ class PlantUmlDumper implements DumperInterface
public function dump(Definition $definition, Marking $marking = null, array $options = []): string
{
$options = array_replace_recursive(self::DEFAULT_OPTIONS, $options);
$code = $this->initialize($options);
$workflowMetadata = $definition->getMetadataStore();
$code = $this->initialize($options, $definition);
foreach ($definition->getPlaces() as $place) {
$placeEscaped = $this->escape($place);
$code[] =
"state $placeEscaped".
($definition->getInitialPlace() === $place ? ' '.self::INITIAL : '').
($marking && $marking->has($place) ? ' '.self::MARKED : '');
$code[] = $this->getState($place, $definition, $marking);
}
if ($this->isWorkflowTransitionType()) {
foreach ($definition->getTransitions() as $transition) {
@ -83,10 +85,26 @@ class PlantUmlDumper implements DumperInterface
$fromEscaped = $this->escape($from);
foreach ($transition->getTos() as $to) {
$toEscaped = $this->escape($to);
$transitionEscapedWithStyle = $this->getTransitionEscapedWithStyle($workflowMetadata, $transition, $transitionEscaped);
$arrowColor = $workflowMetadata->getMetadata('arrow_color', $transition);
$transitionColor = '';
if (null !== $arrowColor) {
$transitionColor = $this->getTransitionColor($arrowColor) ?? '';
}
if ($this->isWorkflowTransitionType()) {
$transitionLabel = '';
// Add label only if it has a style
if ($transitionEscapedWithStyle != $transitionEscaped) {
$transitionLabel = ": $transitionEscapedWithStyle";
}
$lines = [
"$fromEscaped --> $transitionEscaped",
"$transitionEscaped --> $toEscaped",
"$fromEscaped -${transitionColor}-> ${transitionEscaped}${transitionLabel}",
"$transitionEscaped -${transitionColor}-> ${toEscaped}${transitionLabel}",
];
foreach ($lines as $line) {
if (!\in_array($line, $code)) {
@ -94,7 +112,7 @@ class PlantUmlDumper implements DumperInterface
}
}
} else {
$code[] = "$fromEscaped --> $toEscaped: $transitionEscaped";
$code[] = "$fromEscaped -${transitionColor}-> $toEscaped: $transitionEscapedWithStyle";
}
}
}
@ -126,8 +144,10 @@ class PlantUmlDumper implements DumperInterface
return implode(PHP_EOL, $code);
}
private function initialize(array $options): array
private function initialize(array $options, Definition $definition): array
{
$workflowMetadata = $definition->getMetadataStore();
$code = [];
if (isset($options['title'])) {
$code[] = "title {$options['title']}";
@ -135,6 +155,17 @@ class PlantUmlDumper implements DumperInterface
if (isset($options['name'])) {
$code[] = "title {$options['name']}";
}
// Add style from nodes
foreach ($definition->getPlaces() as $place) {
$backgroundColor = $workflowMetadata->getMetadata('bg_color', $place);
if (null !== $backgroundColor) {
$key = 'BackgroundColor<<'.$this->getColorId($backgroundColor).'>>';
$options['skinparams']['state'][$key] = $backgroundColor;
}
}
if (isset($options['skinparams']) && \is_array($options['skinparams'])) {
foreach ($options['skinparams'] as $skinparamKey => $skinparamValue) {
if (!$this->isWorkflowTransitionType() && 'agent' === $skinparamKey) {
@ -160,4 +191,62 @@ class PlantUmlDumper implements DumperInterface
// It's not possible to escape property double quote, so let's remove it
return '"'.str_replace('"', '', $string).'"';
}
private function getState(string $place, Definition $definition, Marking $marking = null): string
{
$workflowMetadata = $definition->getMetadataStore();
$placeEscaped = $this->escape($place);
$output = "state $placeEscaped".
($definition->getInitialPlace() === $place ? ' '.self::INITIAL : '').
($marking && $marking->has($place) ? ' '.self::MARKED : '');
$backgroundColor = $workflowMetadata->getMetadata('bg_color', $place);
if (null !== $backgroundColor) {
$output .= ' <<'.$this->getColorId($backgroundColor).'>>';
}
$description = $workflowMetadata->getMetadata('description', $place);
if (null !== $description) {
$output .= ' as '.$place.
PHP_EOL.
$place.' : '.$description;
}
return $output;
}
private function getTransitionEscapedWithStyle(MetadataStoreInterface $workflowMetadata, Transition $transition, string $to): string
{
$to = $workflowMetadata->getMetadata('label', $transition) ?? $to;
$color = $workflowMetadata->getMetadata('color', $transition) ?? null;
if (null !== $color) {
$to = sprintf(
'<font color=%1$s>%2$s</font>',
$color,
$to
);
}
return $this->escape($to);
}
private function getTransitionColor(string $color): string
{
// PUML format requires that color in transition have to be prefixed with “#”.
if ('#' !== substr($color, 0, 1)) {
$color = '#'.$color;
}
return sprintf('[%s]', $color);
}
private function getColorId(string $color): string
{
// Remove “#“ from start of the color name so it can be used as an identifier.
return ltrim($color, '#');
}
}

View File

@ -46,15 +46,32 @@ class StateMachineGraphvizDumper extends GraphvizDumper
*/
protected function findEdges(Definition $definition)
{
$workflowMetadata = $definition->getMetadataStore();
$edges = [];
foreach ($definition->getTransitions() as $transition) {
$attributes = [];
$transitionName = $workflowMetadata->getMetadata('label', $transition) ?? $transition->getName();
$labelColor = $workflowMetadata->getMetadata('color', $transition);
if (null !== $labelColor) {
$attributes['fontcolor'] = $labelColor;
}
$arrowColor = $workflowMetadata->getMetadata('arrow_color', $transition);
if (null !== $arrowColor) {
$attributes['color'] = $arrowColor;
}
foreach ($transition->getFroms() as $from) {
foreach ($transition->getTos() as $to) {
$edges[$from][] = [
'name' => $transition->getName(),
$edge = [
'name' => $transitionName,
'to' => $to,
'attributes' => $attributes,
];
$edges[$from][] = $edge;
}
}
}
@ -71,7 +88,14 @@ class StateMachineGraphvizDumper extends GraphvizDumper
foreach ($edges as $id => $edges) {
foreach ($edges as $edge) {
$code .= sprintf(" place_%s -> place_%s [label=\"%s\" style=\"%s\"];\n", $this->dotize($id), $this->dotize($edge['to']), $this->escape($edge['name']), 'solid');
$code .= sprintf(
" place_%s -> place_%s [label=\"%s\" style=\"%s\"%s];\n",
$this->dotize($id),
$this->dotize($edge['to']),
$this->escape($edge['name']),
'solid',
$this->addAttributes($edge['attributes'])
);
}
}

View File

@ -66,27 +66,27 @@ class GraphvizDumperTest extends TestCase
node [fontsize="9" fontname="Arial" color="#333333" fillcolor="lightblue" fixedsize="false" width="1"];
edge [fontsize="9" fontname="Arial" color="#333333" arrowhead="normal" arrowsize="0.5"];
place_86f7e437faa5a7fce15d1ddcb9eaeaea377667b8 [label="a", shape=circle, style="filled"];
place_e9d71f5ee7c92d6dc9e92ffdad17b8bd49418f98 [label="b", shape=circle, color="#FF0000", shape="doublecircle"];
place_86f7e437faa5a7fce15d1ddcb9eaeaea377667b8 [label="a", shape=circle style="filled"];
place_e9d71f5ee7c92d6dc9e92ffdad17b8bd49418f98 [label="b", shape=circle color="#FF0000" shape="doublecircle"];
place_84a516841ba77a5b4648de2cd0dfcb30ea46dbb4 [label="c", shape=circle];
place_3c363836cf4e16666669a25da280a1865c2d2874 [label="d", shape=circle];
place_58e6b3a414a1e090dfc6029add0f3555ccba127f [label="e", shape=circle];
place_4a0a19218e082a343a1b17e5333409af9d98f0f5 [label="f", shape=circle];
place_54fd1711209fb1c0781092374132c66e79e2241b [label="g", shape=circle];
transition_e5353879bd69bfddcb465dad176ff52db8319d6f [label="t1", shape=box, shape="box", regular="1"];
transition_2a5bd02710e975a7fbb92da876655950fbd5e70d [label="t2", shape=box, shape="box", regular="1"];
transition_4358694eeb098c6708ae914a10562ce722bbbc34 [label="t3", shape=box, shape="box", regular="1"];
transition_a9dfb15be45a5f3128784c80c733f2cdee2f756a [label="t4", shape=box, shape="box", regular="1"];
transition_bf55e75fa263cbbc2529db49da43cb7f1d370b88 [label="t5", shape=box, shape="box", regular="1"];
transition_e92a96c0e3a20d87ace74ab7871931a8f9f25943 [label="t6", shape=box, shape="box", regular="1"];
transition_e5353879bd69bfddcb465dad176ff52db8319d6f [label="t1", shape="box" regular="1"];
transition_2a5bd02710e975a7fbb92da876655950fbd5e70d [label="t2", shape="box" regular="1"];
transition_0e93386f7fc29aa558e22918bd39c3de8c84f6d8 [label="My custom transition label 1", shape="box" regular="1"];
transition_a9dfb15be45a5f3128784c80c733f2cdee2f756a [label="t4", shape="box" regular="1"];
transition_bf55e75fa263cbbc2529db49da43cb7f1d370b88 [label="t5", shape="box" regular="1"];
transition_e92a96c0e3a20d87ace74ab7871931a8f9f25943 [label="t6", shape="box" regular="1"];
place_86f7e437faa5a7fce15d1ddcb9eaeaea377667b8 -> transition_e5353879bd69bfddcb465dad176ff52db8319d6f [style="solid"];
transition_e5353879bd69bfddcb465dad176ff52db8319d6f -> place_e9d71f5ee7c92d6dc9e92ffdad17b8bd49418f98 [style="solid"];
transition_e5353879bd69bfddcb465dad176ff52db8319d6f -> place_84a516841ba77a5b4648de2cd0dfcb30ea46dbb4 [style="solid"];
place_e9d71f5ee7c92d6dc9e92ffdad17b8bd49418f98 -> transition_2a5bd02710e975a7fbb92da876655950fbd5e70d [style="solid"];
place_84a516841ba77a5b4648de2cd0dfcb30ea46dbb4 -> transition_2a5bd02710e975a7fbb92da876655950fbd5e70d [style="solid"];
transition_2a5bd02710e975a7fbb92da876655950fbd5e70d -> place_3c363836cf4e16666669a25da280a1865c2d2874 [style="solid"];
place_3c363836cf4e16666669a25da280a1865c2d2874 -> transition_4358694eeb098c6708ae914a10562ce722bbbc34 [style="solid"];
transition_4358694eeb098c6708ae914a10562ce722bbbc34 -> place_58e6b3a414a1e090dfc6029add0f3555ccba127f [style="solid"];
place_3c363836cf4e16666669a25da280a1865c2d2874 -> transition_0e93386f7fc29aa558e22918bd39c3de8c84f6d8 [style="solid"];
transition_0e93386f7fc29aa558e22918bd39c3de8c84f6d8 -> place_58e6b3a414a1e090dfc6029add0f3555ccba127f [style="solid"];
place_3c363836cf4e16666669a25da280a1865c2d2874 -> transition_a9dfb15be45a5f3128784c80c733f2cdee2f756a [style="solid"];
transition_a9dfb15be45a5f3128784c80c733f2cdee2f756a -> place_4a0a19218e082a343a1b17e5333409af9d98f0f5 [style="solid"];
place_58e6b3a414a1e090dfc6029add0f3555ccba127f -> transition_bf55e75fa263cbbc2529db49da43cb7f1d370b88 [style="solid"];
@ -104,13 +104,13 @@ class GraphvizDumperTest extends TestCase
node [fontsize="9" fontname="Arial" color="#333333" fillcolor="lightblue" fixedsize="false" width="1"];
edge [fontsize="9" fontname="Arial" color="#333333" arrowhead="normal" arrowsize="0.5"];
place_86f7e437faa5a7fce15d1ddcb9eaeaea377667b8 [label="a", shape=circle, style="filled"];
place_86f7e437faa5a7fce15d1ddcb9eaeaea377667b8 [label="a", shape=circle style="filled"];
place_e9d71f5ee7c92d6dc9e92ffdad17b8bd49418f98 [label="b", shape=circle];
place_84a516841ba77a5b4648de2cd0dfcb30ea46dbb4 [label="c", shape=circle, color="#FF0000", shape="doublecircle"];
transition_e5353879bd69bfddcb465dad176ff52db8319d6f [label="t1", shape=box, shape="box", regular="1"];
transition_2a5bd02710e975a7fbb92da876655950fbd5e70d [label="t2", shape=box, shape="box", regular="1"];
place_86f7e437faa5a7fce15d1ddcb9eaeaea377667b8 -> transition_e5353879bd69bfddcb465dad176ff52db8319d6f [style="solid"];
transition_e5353879bd69bfddcb465dad176ff52db8319d6f -> place_e9d71f5ee7c92d6dc9e92ffdad17b8bd49418f98 [style="solid"];
place_84a516841ba77a5b4648de2cd0dfcb30ea46dbb4 [label="c", shape=circle color="#FF0000" shape="doublecircle" style="filled" fillcolor="DeepSkyBlue"];
transition_805bac6f9261aaae4068bf114e182e9c37e2728d [label="My custom transition label 2", shape="box" regular="1"];
transition_2a5bd02710e975a7fbb92da876655950fbd5e70d [label="t2", shape="box" regular="1"];
place_86f7e437faa5a7fce15d1ddcb9eaeaea377667b8 -> transition_805bac6f9261aaae4068bf114e182e9c37e2728d [style="solid"];
transition_805bac6f9261aaae4068bf114e182e9c37e2728d -> place_e9d71f5ee7c92d6dc9e92ffdad17b8bd49418f98 [style="solid"];
place_e9d71f5ee7c92d6dc9e92ffdad17b8bd49418f98 -> transition_2a5bd02710e975a7fbb92da876655950fbd5e70d [style="solid"];
transition_2a5bd02710e975a7fbb92da876655950fbd5e70d -> place_84a516841ba77a5b4648de2cd0dfcb30ea46dbb4 [style="solid"];
}
@ -124,27 +124,27 @@ class GraphvizDumperTest extends TestCase
node [fontsize="9" fontname="Arial" color="#333333" fillcolor="lightblue" fixedsize="false" width="1"];
edge [fontsize="9" fontname="Arial" color="#333333" arrowhead="normal" arrowsize="0.5"];
place_86f7e437faa5a7fce15d1ddcb9eaeaea377667b8 [label="a", shape=circle, style="filled"];
place_86f7e437faa5a7fce15d1ddcb9eaeaea377667b8 [label="a", shape=circle style="filled"];
place_e9d71f5ee7c92d6dc9e92ffdad17b8bd49418f98 [label="b", shape=circle];
place_84a516841ba77a5b4648de2cd0dfcb30ea46dbb4 [label="c", shape=circle];
place_3c363836cf4e16666669a25da280a1865c2d2874 [label="d", shape=circle];
place_58e6b3a414a1e090dfc6029add0f3555ccba127f [label="e", shape=circle];
place_4a0a19218e082a343a1b17e5333409af9d98f0f5 [label="f", shape=circle];
place_54fd1711209fb1c0781092374132c66e79e2241b [label="g", shape=circle];
transition_e5353879bd69bfddcb465dad176ff52db8319d6f [label="t1", shape=box, shape="box", regular="1"];
transition_2a5bd02710e975a7fbb92da876655950fbd5e70d [label="t2", shape=box, shape="box", regular="1"];
transition_4358694eeb098c6708ae914a10562ce722bbbc34 [label="t3", shape=box, shape="box", regular="1"];
transition_a9dfb15be45a5f3128784c80c733f2cdee2f756a [label="t4", shape=box, shape="box", regular="1"];
transition_bf55e75fa263cbbc2529db49da43cb7f1d370b88 [label="t5", shape=box, shape="box", regular="1"];
transition_e92a96c0e3a20d87ace74ab7871931a8f9f25943 [label="t6", shape=box, shape="box", regular="1"];
transition_e5353879bd69bfddcb465dad176ff52db8319d6f [label="t1", shape="box" regular="1"];
transition_2a5bd02710e975a7fbb92da876655950fbd5e70d [label="t2", shape="box" regular="1"];
transition_0e93386f7fc29aa558e22918bd39c3de8c84f6d8 [label="My custom transition label 1", shape="box" regular="1"];
transition_a9dfb15be45a5f3128784c80c733f2cdee2f756a [label="t4", shape="box" regular="1"];
transition_bf55e75fa263cbbc2529db49da43cb7f1d370b88 [label="t5", shape="box" regular="1"];
transition_e92a96c0e3a20d87ace74ab7871931a8f9f25943 [label="t6", shape="box" regular="1"];
place_86f7e437faa5a7fce15d1ddcb9eaeaea377667b8 -> transition_e5353879bd69bfddcb465dad176ff52db8319d6f [style="solid"];
transition_e5353879bd69bfddcb465dad176ff52db8319d6f -> place_e9d71f5ee7c92d6dc9e92ffdad17b8bd49418f98 [style="solid"];
transition_e5353879bd69bfddcb465dad176ff52db8319d6f -> place_84a516841ba77a5b4648de2cd0dfcb30ea46dbb4 [style="solid"];
place_e9d71f5ee7c92d6dc9e92ffdad17b8bd49418f98 -> transition_2a5bd02710e975a7fbb92da876655950fbd5e70d [style="solid"];
place_84a516841ba77a5b4648de2cd0dfcb30ea46dbb4 -> transition_2a5bd02710e975a7fbb92da876655950fbd5e70d [style="solid"];
transition_2a5bd02710e975a7fbb92da876655950fbd5e70d -> place_3c363836cf4e16666669a25da280a1865c2d2874 [style="solid"];
place_3c363836cf4e16666669a25da280a1865c2d2874 -> transition_4358694eeb098c6708ae914a10562ce722bbbc34 [style="solid"];
transition_4358694eeb098c6708ae914a10562ce722bbbc34 -> place_58e6b3a414a1e090dfc6029add0f3555ccba127f [style="solid"];
place_3c363836cf4e16666669a25da280a1865c2d2874 -> transition_0e93386f7fc29aa558e22918bd39c3de8c84f6d8 [style="solid"];
transition_0e93386f7fc29aa558e22918bd39c3de8c84f6d8 -> place_58e6b3a414a1e090dfc6029add0f3555ccba127f [style="solid"];
place_3c363836cf4e16666669a25da280a1865c2d2874 -> transition_a9dfb15be45a5f3128784c80c733f2cdee2f756a [style="solid"];
transition_a9dfb15be45a5f3128784c80c733f2cdee2f756a -> place_4a0a19218e082a343a1b17e5333409af9d98f0f5 [style="solid"];
place_58e6b3a414a1e090dfc6029add0f3555ccba127f -> transition_bf55e75fa263cbbc2529db49da43cb7f1d370b88 [style="solid"];
@ -162,13 +162,13 @@ class GraphvizDumperTest extends TestCase
node [fontsize="9" fontname="Arial" color="#333333" fillcolor="lightblue" fixedsize="false" width="1"];
edge [fontsize="9" fontname="Arial" color="#333333" arrowhead="normal" arrowsize="0.5"];
place_86f7e437faa5a7fce15d1ddcb9eaeaea377667b8 [label="a", shape=circle, style="filled"];
place_86f7e437faa5a7fce15d1ddcb9eaeaea377667b8 [label="a", shape=circle style="filled"];
place_e9d71f5ee7c92d6dc9e92ffdad17b8bd49418f98 [label="b", shape=circle];
place_84a516841ba77a5b4648de2cd0dfcb30ea46dbb4 [label="c", shape=circle];
transition_e5353879bd69bfddcb465dad176ff52db8319d6f [label="t1", shape=box, shape="box", regular="1"];
transition_2a5bd02710e975a7fbb92da876655950fbd5e70d [label="t2", shape=box, shape="box", regular="1"];
place_86f7e437faa5a7fce15d1ddcb9eaeaea377667b8 -> transition_e5353879bd69bfddcb465dad176ff52db8319d6f [style="solid"];
transition_e5353879bd69bfddcb465dad176ff52db8319d6f -> place_e9d71f5ee7c92d6dc9e92ffdad17b8bd49418f98 [style="solid"];
place_84a516841ba77a5b4648de2cd0dfcb30ea46dbb4 [label="c", shape=circle style="filled" fillcolor="DeepSkyBlue"];
transition_805bac6f9261aaae4068bf114e182e9c37e2728d [label="My custom transition label 2", shape="box" regular="1"];
transition_2a5bd02710e975a7fbb92da876655950fbd5e70d [label="t2", shape="box" regular="1"];
place_86f7e437faa5a7fce15d1ddcb9eaeaea377667b8 -> transition_805bac6f9261aaae4068bf114e182e9c37e2728d [style="solid"];
transition_805bac6f9261aaae4068bf114e182e9c37e2728d -> place_e9d71f5ee7c92d6dc9e92ffdad17b8bd49418f98 [style="solid"];
place_e9d71f5ee7c92d6dc9e92ffdad17b8bd49418f98 -> transition_2a5bd02710e975a7fbb92da876655950fbd5e70d [style="solid"];
transition_2a5bd02710e975a7fbb92da876655950fbd5e70d -> place_84a516841ba77a5b4648de2cd0dfcb30ea46dbb4 [style="solid"];
}

View File

@ -30,13 +30,13 @@ digraph workflow {
node [fontsize="9" fontname="Arial" color="#333333" fillcolor="lightblue" fixedsize="false" width="1"];
edge [fontsize="9" fontname="Arial" color="#333333" arrowhead="normal" arrowsize="0.5"];
place_86f7e437faa5a7fce15d1ddcb9eaeaea377667b8 [label="a", shape=circle, style="filled"];
place_86f7e437faa5a7fce15d1ddcb9eaeaea377667b8 [label="a", shape=circle style="filled"];
place_e9d71f5ee7c92d6dc9e92ffdad17b8bd49418f98 [label="b", shape=circle];
place_84a516841ba77a5b4648de2cd0dfcb30ea46dbb4 [label="c", shape=circle];
place_3c363836cf4e16666669a25da280a1865c2d2874 [label="d", shape=circle];
place_86f7e437faa5a7fce15d1ddcb9eaeaea377667b8 -> place_e9d71f5ee7c92d6dc9e92ffdad17b8bd49418f98 [label="t1" style="solid"];
place_3c363836cf4e16666669a25da280a1865c2d2874 -> place_e9d71f5ee7c92d6dc9e92ffdad17b8bd49418f98 [label="t1" style="solid"];
place_e9d71f5ee7c92d6dc9e92ffdad17b8bd49418f98 -> place_84a516841ba77a5b4648de2cd0dfcb30ea46dbb4 [label="t2" style="solid"];
place_3c363836cf4e16666669a25da280a1865c2d2874 -> place_e9d71f5ee7c92d6dc9e92ffdad17b8bd49418f98 [label="My custom transition label 3" style="solid" fontcolor="Grey" color="Red"];
place_e9d71f5ee7c92d6dc9e92ffdad17b8bd49418f98 -> place_84a516841ba77a5b4648de2cd0dfcb30ea46dbb4 [label="t2" style="solid" color="Blue"];
place_e9d71f5ee7c92d6dc9e92ffdad17b8bd49418f98 -> place_3c363836cf4e16666669a25da280a1865c2d2874 [label="t3" style="solid"];
}
@ -56,13 +56,13 @@ digraph workflow {
node [fontsize="9" fontname="Arial" color="#333333" fillcolor="lightblue" fixedsize="false" width="1"];
edge [fontsize="9" fontname="Arial" color="#333333" arrowhead="normal" arrowsize="0.5"];
place_86f7e437faa5a7fce15d1ddcb9eaeaea377667b8 [label="a", shape=circle, style="filled"];
place_e9d71f5ee7c92d6dc9e92ffdad17b8bd49418f98 [label="b", shape=circle, color="#FF0000", shape="doublecircle"];
place_86f7e437faa5a7fce15d1ddcb9eaeaea377667b8 [label="a", shape=circle style="filled"];
place_e9d71f5ee7c92d6dc9e92ffdad17b8bd49418f98 [label="b", shape=circle color="#FF0000" shape="doublecircle"];
place_84a516841ba77a5b4648de2cd0dfcb30ea46dbb4 [label="c", shape=circle];
place_3c363836cf4e16666669a25da280a1865c2d2874 [label="d", shape=circle];
place_86f7e437faa5a7fce15d1ddcb9eaeaea377667b8 -> place_e9d71f5ee7c92d6dc9e92ffdad17b8bd49418f98 [label="t1" style="solid"];
place_3c363836cf4e16666669a25da280a1865c2d2874 -> place_e9d71f5ee7c92d6dc9e92ffdad17b8bd49418f98 [label="t1" style="solid"];
place_e9d71f5ee7c92d6dc9e92ffdad17b8bd49418f98 -> place_84a516841ba77a5b4648de2cd0dfcb30ea46dbb4 [label="t2" style="solid"];
place_3c363836cf4e16666669a25da280a1865c2d2874 -> place_e9d71f5ee7c92d6dc9e92ffdad17b8bd49418f98 [label="My custom transition label 3" style="solid" fontcolor="Grey" color="Red"];
place_e9d71f5ee7c92d6dc9e92ffdad17b8bd49418f98 -> place_84a516841ba77a5b4648de2cd0dfcb30ea46dbb4 [label="t2" style="solid" color="Blue"];
place_e9d71f5ee7c92d6dc9e92ffdad17b8bd49418f98 -> place_3c363836cf4e16666669a25da280a1865c2d2874 [label="t3" style="solid"];
}

View File

@ -3,6 +3,7 @@
namespace Symfony\Component\Workflow\Tests;
use Symfony\Component\Workflow\Definition;
use Symfony\Component\Workflow\Metadata\InMemoryMetadataStore;
use Symfony\Component\Workflow\Transition;
trait WorkflowBuilderTrait
@ -14,12 +15,21 @@ trait WorkflowBuilderTrait
$transitions = [];
$transitions[] = new Transition('t1', 'a', ['b', 'c']);
$transitions[] = new Transition('t2', ['b', 'c'], 'd');
$transitions[] = new Transition('t3', 'd', 'e');
$transitionWithMetadataDumpStyle = new Transition('t3', 'd', 'e');
$transitions[] = $transitionWithMetadataDumpStyle;
$transitions[] = new Transition('t4', 'd', 'f');
$transitions[] = new Transition('t5', 'e', 'g');
$transitions[] = new Transition('t6', 'f', 'g');
return new Definition($places, $transitions);
$transitionsMetadata = new \SplObjectStorage();
$transitionsMetadata[$transitionWithMetadataDumpStyle] = [
'label' => 'My custom transition label 1',
'color' => 'Red',
'arrow_color' => 'Green',
];
$inMemoryMetadataStore = new InMemoryMetadataStore([], [], $transitionsMetadata);
return new Definition($places, $transitions, null, $inMemoryMetadataStore);
// The graph looks like:
// +---+ +----+ +---+ +----+ +----+ +----+ +----+ +----+ +---+
@ -38,10 +48,28 @@ trait WorkflowBuilderTrait
$places = range('a', 'c');
$transitions = [];
$transitions[] = new Transition('t1', 'a', 'b');
$transitions[] = new Transition('t2', 'b', 'c');
$transitionWithMetadataDumpStyle = new Transition('t1', 'a', 'b');
$transitions[] = $transitionWithMetadataDumpStyle;
$transitionWithMetadataArrowColorPink = new Transition('t2', 'b', 'c');
$transitions[] = $transitionWithMetadataArrowColorPink;
return new Definition($places, $transitions);
$placesMetadata = [];
$placesMetadata['c'] = [
'bg_color' => 'DeepSkyBlue',
];
$transitionsMetadata = new \SplObjectStorage();
$transitionsMetadata[$transitionWithMetadataDumpStyle] = [
'label' => 'My custom transition label 2',
'color' => 'Grey',
'arrow_color' => 'Purple',
];
$transitionsMetadata[$transitionWithMetadataArrowColorPink] = [
'arrow_color' => 'Pink',
];
$inMemoryMetadataStore = new InMemoryMetadataStore([], $placesMetadata, $transitionsMetadata);
return new Definition($places, $transitions, null, $inMemoryMetadataStore);
// The graph looks like:
// +---+ +----+ +---+ +----+ +---+
@ -82,13 +110,24 @@ trait WorkflowBuilderTrait
$places = ['a', 'b', 'c', 'd'];
$transitions[] = new Transition('t1', 'a', 'b');
$transitions[] = new Transition('t1', 'd', 'b');
$transitions[] = new Transition('t2', 'b', 'c');
$transitionWithMetadataDumpStyle = new Transition('t1', 'd', 'b');
$transitions[] = $transitionWithMetadataDumpStyle;
$transitionWithMetadataArrowColorBlue = new Transition('t2', 'b', 'c');
$transitions[] = $transitionWithMetadataArrowColorBlue;
$transitions[] = new Transition('t3', 'b', 'd');
$definition = new Definition($places, $transitions);
$transitionsMetadata = new \SplObjectStorage();
$transitionsMetadata[$transitionWithMetadataDumpStyle] = [
'label' => 'My custom transition label 3',
'color' => 'Grey',
'arrow_color' => 'Red',
];
$transitionsMetadata[$transitionWithMetadataArrowColorBlue] = [
'arrow_color' => 'Blue',
];
$inMemoryMetadataStore = new InMemoryMetadataStore([], [], $transitionsMetadata);
return $definition;
return new Definition($places, $transitions, null, $inMemoryMetadataStore);
// The graph looks like:
// t1

View File

@ -15,7 +15,7 @@ state "b"
state "c" <<marked>>
state "d"
"a" --> "b": "t1"
"d" --> "b": "t1"
"b" --> "c": "t2"
"d" -[#Red]-> "b": "<font color=Grey>My custom transition label 3</font>"
"b" -[#Blue]-> "c": "t2"
"b" --> "d": "t3"
@enduml

View File

@ -15,7 +15,7 @@ state "b"
state "c"
state "d"
"a" --> "b": "t1"
"d" --> "b": "t1"
"b" --> "c": "t2"
"d" -[#Red]-> "b": "<font color=Grey>My custom transition label 3</font>"
"b" -[#Blue]-> "c": "t2"
"b" --> "d": "t3"
@enduml

View File

@ -33,8 +33,8 @@ agent "t6"
"b" --> "t2"
"t2" --> "d"
"c" --> "t2"
"d" --> "t3"
"t3" --> "e"
"d" -[#Green]-> "t3": "<font color=Red>My custom transition label 1</font>"
"t3" -[#Green]-> "e": "<font color=Red>My custom transition label 1</font>"
"d" --> "t4"
"t4" --> "f"
"e" --> "t5"

View File

@ -33,8 +33,8 @@ agent "t6"
"b" --> "t2"
"t2" --> "d"
"c" --> "t2"
"d" --> "t3"
"t3" --> "e"
"d" -[#Green]-> "t3": "<font color=Red>My custom transition label 1</font>"
"t3" -[#Green]-> "e": "<font color=Red>My custom transition label 1</font>"
"d" --> "t4"
"t4" --> "f"
"e" --> "t5"

View File

@ -9,6 +9,7 @@ skinparam state {
BorderColor #3887C6
BorderColor<<marked>> Black
FontColor<<marked>> White
BackgroundColor<<DeepSkyBlue>> DeepSkyBlue
}
skinparam agent {
BackgroundColor #ffffff
@ -16,11 +17,11 @@ skinparam agent {
}
state "a" <<initial>>
state "b" <<marked>>
state "c"
state "c" <<DeepSkyBlue>>
agent "t1"
agent "t2"
"a" --> "t1"
"t1" --> "b"
"b" --> "t2"
"t2" --> "c"
"a" -[#Purple]-> "t1": "<font color=Grey>My custom transition label 2</font>"
"t1" -[#Purple]-> "b": "<font color=Grey>My custom transition label 2</font>"
"b" -[#Pink]-> "t2"
"t2" -[#Pink]-> "c"
@enduml

View File

@ -9,6 +9,7 @@ skinparam state {
BorderColor #3887C6
BorderColor<<marked>> Black
FontColor<<marked>> White
BackgroundColor<<DeepSkyBlue>> DeepSkyBlue
}
skinparam agent {
BackgroundColor #ffffff
@ -16,11 +17,11 @@ skinparam agent {
}
state "a" <<initial>>
state "b"
state "c"
state "c" <<DeepSkyBlue>>
agent "t1"
agent "t2"
"a" --> "t1"
"t1" --> "b"
"b" --> "t2"
"t2" --> "c"
"a" -[#Purple]-> "t1": "<font color=Grey>My custom transition label 2</font>"
"t1" -[#Purple]-> "b": "<font color=Grey>My custom transition label 2</font>"
"b" -[#Pink]-> "t2"
"t2" -[#Pink]-> "c"
@enduml