14
14
use InvalidArgumentException ;
15
15
use Symfony \Component \Workflow \Definition ;
16
16
use Symfony \Component \Workflow \Marking ;
17
+ use Symfony \Component \Workflow \Metadata \MetadataStoreInterface ;
18
+ use Symfony \Component \Workflow \Transition ;
17
19
18
20
/**
19
21
* PlantUmlDumper dumps a workflow as a PlantUML file.
@@ -63,13 +65,13 @@ public function __construct(string $transitionType = null)
63
65
public function dump (Definition $ definition , Marking $ marking = null , array $ options = []): string
64
66
{
65
67
$ options = array_replace_recursive (self ::DEFAULT_OPTIONS , $ options );
66
- $ code = $ this ->initialize ($ options );
68
+
69
+ $ workflowMetadata = $ definition ->getMetadataStore ();
70
+
71
+ $ code = $ this ->initialize ($ options , $ definition );
72
+
67
73
foreach ($ definition ->getPlaces () as $ place ) {
68
- $ placeEscaped = $ this ->escape ($ place );
69
- $ code [] =
70
- "state $ placeEscaped " .
71
- ($ definition ->getInitialPlace () === $ place ? ' ' .self ::INITIAL : '' ).
72
- ($ marking && $ marking ->has ($ place ) ? ' ' .self ::MARKED : '' );
74
+ $ code [] = $ this ->getState ($ place , $ definition , $ marking );
73
75
}
74
76
if ($ this ->isWorkflowTransitionType ()) {
75
77
foreach ($ definition ->getTransitions () as $ transition ) {
@@ -83,18 +85,34 @@ public function dump(Definition $definition, Marking $marking = null, array $opt
83
85
$ fromEscaped = $ this ->escape ($ from );
84
86
foreach ($ transition ->getTos () as $ to ) {
85
87
$ toEscaped = $ this ->escape ($ to );
88
+
89
+ $ transitionEscapedWithStyle = $ this ->getTransitionEscapedWithStyle ($ workflowMetadata , $ transition , $ transitionEscaped );
90
+
91
+ $ arrowColor = $ workflowMetadata ->getMetadata ('arrow_color ' , $ transition );
92
+
93
+ $ transitionColor = '' ;
94
+ if (null !== $ arrowColor ) {
95
+ $ transitionColor = $ this ->getTransitionColor ($ arrowColor ) ?? '' ;
96
+ }
97
+
86
98
if ($ this ->isWorkflowTransitionType ()) {
99
+ $ transitionLabel = '' ;
100
+ // Add label only if it has a style
101
+ if ($ transitionEscapedWithStyle != $ transitionEscaped ) {
102
+ $ transitionLabel = ": $ transitionEscapedWithStyle " ;
103
+ }
104
+
87
105
$ lines = [
88
- "$ fromEscaped --> $ transitionEscaped " ,
89
- "$ transitionEscaped --> $ toEscaped " ,
106
+ "$ fromEscaped - $ {transitionColor} -> $ { transitionEscaped} $ {transitionLabel} " ,
107
+ "$ transitionEscaped - $ {transitionColor} -> $ { toEscaped} $ {transitionLabel} " ,
90
108
];
91
109
foreach ($ lines as $ line ) {
92
110
if (!\in_array ($ line , $ code )) {
93
111
$ code [] = $ line ;
94
112
}
95
113
}
96
114
} else {
97
- $ code [] = "$ fromEscaped --> $ toEscaped: $ transitionEscaped " ;
115
+ $ code [] = "$ fromEscaped - $ {transitionColor} -> $ toEscaped: $ transitionEscapedWithStyle " ;
98
116
}
99
117
}
100
118
}
@@ -126,15 +144,28 @@ private function getLines(array $code): string
126
144
return implode (PHP_EOL , $ code );
127
145
}
128
146
129
- private function initialize (array $ options ): array
147
+ private function initialize (array $ options, Definition $ definition ): array
130
148
{
149
+ $ workflowMetadata = $ definition ->getMetadataStore ();
150
+
131
151
$ code = [];
132
152
if (isset ($ options ['title ' ])) {
133
153
$ code [] = "title {$ options ['title ' ]}" ;
134
154
}
135
155
if (isset ($ options ['name ' ])) {
136
156
$ code [] = "title {$ options ['name ' ]}" ;
137
157
}
158
+
159
+ // Add style from nodes
160
+ foreach ($ definition ->getPlaces () as $ place ) {
161
+ $ backgroundColor = $ workflowMetadata ->getMetadata ('bg_color ' , $ place );
162
+ if (null !== $ backgroundColor ) {
163
+ $ key = 'BackgroundColor<< ' .$ this ->getColorId ($ backgroundColor ).'>> ' ;
164
+
165
+ $ options ['skinparams ' ]['state ' ][$ key ] = $ backgroundColor ;
166
+ }
167
+ }
168
+
138
169
if (isset ($ options ['skinparams ' ]) && \is_array ($ options ['skinparams ' ])) {
139
170
foreach ($ options ['skinparams ' ] as $ skinparamKey => $ skinparamValue ) {
140
171
if (!$ this ->isWorkflowTransitionType () && 'agent ' === $ skinparamKey ) {
@@ -160,4 +191,62 @@ private function escape(string $string): string
160
191
// It's not possible to escape property double quote, so let's remove it
161
192
return '" ' .str_replace ('" ' , '' , $ string ).'" ' ;
162
193
}
194
+
195
+ private function getState (string $ place , Definition $ definition , Marking $ marking = null ): string
196
+ {
197
+ $ workflowMetadata = $ definition ->getMetadataStore ();
198
+
199
+ $ placeEscaped = $ this ->escape ($ place );
200
+
201
+ $ output = "state $ placeEscaped " .
202
+ ($ definition ->getInitialPlace () === $ place ? ' ' .self ::INITIAL : '' ).
203
+ ($ marking && $ marking ->has ($ place ) ? ' ' .self ::MARKED : '' );
204
+
205
+ $ backgroundColor = $ workflowMetadata ->getMetadata ('bg_color ' , $ place );
206
+ if (null !== $ backgroundColor ) {
207
+ $ output .= ' << ' .$ this ->getColorId ($ backgroundColor ).'>> ' ;
208
+ }
209
+
210
+ $ description = $ workflowMetadata ->getMetadata ('description ' , $ place );
211
+ if (null !== $ description ) {
212
+ $ output .= ' as ' .$ place .
213
+ PHP_EOL .
214
+ $ place .' : ' .$ description ;
215
+ }
216
+
217
+ return $ output ;
218
+ }
219
+
220
+ private function getTransitionEscapedWithStyle (MetadataStoreInterface $ workflowMetadata , Transition $ transition , string $ to ): string
221
+ {
222
+ $ to = $ workflowMetadata ->getMetadata ('label ' , $ transition ) ?? $ to ;
223
+
224
+ $ color = $ workflowMetadata ->getMetadata ('color ' , $ transition ) ?? null ;
225
+
226
+ if (null !== $ color ) {
227
+ $ to = sprintf (
228
+ '<font color=%1$s>%2$s</font> ' ,
229
+ $ color ,
230
+ $ to
231
+ );
232
+ }
233
+
234
+ return $ this ->escape ($ to );
235
+ }
236
+
237
+ private function getTransitionColor (string $ color ): string
238
+ {
239
+ // PUML format requires that color in transition have to be prefixed with “#”.
240
+ if ('# ' !== substr ($ color , 0 , 1 )) {
241
+ $ color = '# ' .$ color ;
242
+ }
243
+
244
+ return sprintf ('[%s] ' , $ color );
245
+ }
246
+
247
+ private function getColorId (string $ color ): string
248
+ {
249
+ // Remove “#“ from start of the color name so it can be used as an identifier.
250
+ return ltrim ($ color , '# ' );
251
+ }
163
252
}
0 commit comments