@@ -44,23 +44,27 @@ class GraphvizDumper implements DumperInterface
44
44
*/
45
45
public function dump (Definition $ definition , Marking $ marking = null , array $ options = []): string
46
46
{
47
- $ places = $ this ->findPlaces ($ definition , $ marking );
48
- $ transitions = $ this ->findTransitions ($ definition );
47
+ $ withMetadata = $ options ['with-metadata ' ] ?? false ;
48
+
49
+ $ places = $ this ->findPlaces ($ definition , $ withMetadata , $ marking );
50
+ $ transitions = $ this ->findTransitions ($ definition , $ withMetadata );
49
51
$ edges = $ this ->findEdges ($ definition );
50
52
51
53
$ options = array_replace_recursive (self ::$ defaultOptions , $ options );
52
54
53
- return $ this ->startDot ($ options )
54
- .$ this ->addPlaces ($ places )
55
- .$ this ->addTransitions ($ transitions )
55
+ $ label = $ this ->formatLabel ($ definition , $ withMetadata , $ options );
56
+
57
+ return $ this ->startDot ($ options , $ label )
58
+ .$ this ->addPlaces ($ places , $ withMetadata )
59
+ .$ this ->addTransitions ($ transitions , $ withMetadata )
56
60
.$ this ->addEdges ($ edges )
57
61
.$ this ->endDot ();
58
62
}
59
63
60
64
/**
61
65
* @internal
62
66
*/
63
- protected function findPlaces (Definition $ definition , Marking $ marking = null ): array
67
+ protected function findPlaces (Definition $ definition , bool $ withMetadata , Marking $ marking = null ): array
64
68
{
65
69
$ workflowMetadata = $ definition ->getMetadataStore ();
66
70
@@ -80,9 +84,16 @@ protected function findPlaces(Definition $definition, Marking $marking = null):
80
84
$ attributes ['style ' ] = 'filled ' ;
81
85
$ attributes ['fillcolor ' ] = $ backgroundColor ;
82
86
}
87
+ if ($ withMetadata ) {
88
+ $ attributes ['metadata ' ] = $ workflowMetadata ->getPlaceMetadata ($ place );
89
+ }
83
90
$ label = $ workflowMetadata ->getMetadata ('label ' , $ place );
84
91
if (null !== $ label ) {
85
92
$ attributes ['name ' ] = $ label ;
93
+ if ($ withMetadata ) {
94
+ // Don't include label in metadata if already used as name
95
+ unset($ attributes ['metadata ' ]['label ' ]);
96
+ }
86
97
}
87
98
$ places [$ place ] = [
88
99
'attributes ' => $ attributes ,
@@ -95,7 +106,7 @@ protected function findPlaces(Definition $definition, Marking $marking = null):
95
106
/**
96
107
* @internal
97
108
*/
98
- protected function findTransitions (Definition $ definition ): array
109
+ protected function findTransitions (Definition $ definition, bool $ withMetadata ): array
99
110
{
100
111
$ workflowMetadata = $ definition ->getMetadataStore ();
101
112
@@ -111,9 +122,16 @@ protected function findTransitions(Definition $definition): array
111
122
}
112
123
$ name = $ workflowMetadata ->getMetadata ('label ' , $ transition ) ?? $ transition ->getName ();
113
124
125
+ $ metadata = [];
126
+ if ($ withMetadata ) {
127
+ $ metadata = $ workflowMetadata ->getTransitionMetadata ($ transition );
128
+ unset($ metadata ['label ' ]);
129
+ }
130
+
114
131
$ transitions [] = [
115
132
'attributes ' => $ attributes ,
116
133
'name ' => $ name ,
134
+ 'metadata ' => $ metadata ,
117
135
];
118
136
}
119
137
@@ -123,7 +141,7 @@ protected function findTransitions(Definition $definition): array
123
141
/**
124
142
* @internal
125
143
*/
126
- protected function addPlaces (array $ places ): string
144
+ protected function addPlaces (array $ places, float $ withMetadata ): string
127
145
{
128
146
$ code = '' ;
129
147
@@ -135,7 +153,15 @@ protected function addPlaces(array $places): string
135
153
$ placeName = $ id ;
136
154
}
137
155
138
- $ code .= sprintf (" place_%s [label= \"%s \", shape=circle%s]; \n" , $ this ->dotize ($ id ), $ this ->escape ($ placeName ), $ this ->addAttributes ($ place ['attributes ' ]));
156
+ if ($ withMetadata ) {
157
+ $ escapedLabel = sprintf ('<<B>%s</B>%s> ' , $ this ->escape ($ placeName ), $ this ->addMetadata ($ place ['attributes ' ]['metadata ' ]));
158
+ // Don't include metadata in default attributes used to format the place
159
+ unset($ place ['attributes ' ]['metadata ' ]);
160
+ } else {
161
+ $ escapedLabel = sprintf ('"%s" ' , $ this ->escape ($ placeName ));
162
+ }
163
+
164
+ $ code .= sprintf (" place_%s [label=%s, shape=circle%s]; \n" , $ this ->dotize ($ id ), $ escapedLabel , $ this ->addAttributes ($ place ['attributes ' ]));
139
165
}
140
166
141
167
return $ code ;
@@ -144,12 +170,18 @@ protected function addPlaces(array $places): string
144
170
/**
145
171
* @internal
146
172
*/
F42D
147
- protected function addTransitions (array $ transitions ): string
173
+ protected function addTransitions (array $ transitions, bool $ withMetadata ): string
148
174
{
149
175
$ code = '' ;
150
176
151
177
foreach ($ transitions as $ i => $ place ) {
152
- $ code .= sprintf (" transition_%s [label= \"%s \",%s]; \n" , $ this ->dotize ($ i ), $ this ->escape ($ place ['name ' ]), $ this ->addAttributes ($ place ['attributes ' ]));
178
+ if ($ withMetadata ) {
179
+ $ escapedLabel = sprintf ('<<B>%s</B>%s> ' , $ this ->escape ($ place ['name ' ]), $ this ->addMetadata ($ place ['metadata ' ]));
180
+ } else {
181
+ $ escapedLabel = '" ' .$ this ->escape ($ place ['name ' ]).'" ' ;
182
+ }
183
+
184
+ $ code .= sprintf (" transition_%s [label=%s,%s]; \n" , $ this ->dotize ($ i ), $ escapedLabel , $ this ->addAttributes ($ place ['attributes ' ]));
153
185
}
154
186
155
187
return $ code ;
@@ -215,10 +247,11 @@ protected function addEdges(array $edges): string
215
247
/**
216
248
* @internal
217
249
*/
218
- protected function startDot (array $ options ): string
250
+ protected function startDot (array $ options, string $ label ): string
219
251
{
220
- return sprintf ("digraph workflow { \n %s \n node [%s]; \n edge [%s]; \n\n" ,
252
+ return sprintf ("digraph workflow { \n %s%s \n node [%s]; \n edge [%s]; \n\n" ,
221
253
$ this ->addOptions ($ options ['graph ' ]),
254
+ '"" ' !== $ label && '<> ' !== $ label ? sprintf (' label=%s ' , $ label ) : '' ,
222
255
$ this ->addOptions ($ options ['node ' ]),
223
256
$ this ->addOptions ($ options ['edge ' ])
224
257
);
@@ -248,6 +281,9 @@ protected function escape(string|bool $value): string
248
281
return \is_bool ($ value ) ? ($ value ? '1 ' : '0 ' ) : addslashes ($ value );
249
282
}
250
283
284
+ /**
285
+ * @internal
286
+ */
251
287
protected function addAttributes (array $ attributes ): string
252
288
{
253
289
$ code = [];
@@ -259,6 +295,33 @@ protected function addAttributes(array $attributes): string
259
295
return $ code ? ' ' .implode (' ' , $ code ) : '' ;
260
296
}
261
297
298
+ /**
299
+ * Handles the label of the graph depending on whether a label was set in CLI,
300
+ * if metadata should be included and if there are any.
301
+ *
302
+ * The produced label must be escaped.
303
+ *
304
+ * @internal
305
+ */
306
+ protected function formatLabel (Definition $ definition , string $ withMetadata , array $ options ): string
307
+ {
308
+ $ currentLabel = $ options ['label ' ] ?? '' ;
309
+
310
+ if (!$ withMetadata ) {
311
+ // Only currentLabel to handle. If null, will be translated to empty string
312
+ return sprintf ('"%s" ' , $ this ->escape ($ currentLabel ));
313
+ }
314
+ $ workflowMetadata = $ definition ->getMetadataStore ()->getWorkflowMetadata ();
315
+
316
+ if ('' === $ currentLabel ) {
317
+ // Only metadata to handle
318
+ return sprintf ('<%s> ' , $ this ->addMetadata ($ workflowMetadata , false ));
319
+ }
320
+
321
+ // currentLabel and metadata to handle
322
+ return sprintf ('<<B>%s</B>%s> ' , $ this ->escape ($ currentLabel ), $ this ->addMetadata ($ workflowMetadata ));
323
+ }
324
+
262
325
private function addOptions (array $ options ): string
263
326
{
264
327
$ code = [];
@@ -269,4 +332,25 @@ private function addOptions(array $options): string
269
332
270
333
return implode (' ' , $ code );
271
334
}
335
+
336
+ /**
337
+ * @param bool $lineBreakFirstIfNotEmpty Whether to add a separator in the first place when metadata is not empty
338
+ */
339
+ private function addMetadata (array $ metadata , bool $ lineBreakFirstIfNotEmpty = true ): string
340
+ {
341
+ $ code = [];
342
+
343
+ $ skipSeparator = !$ lineBreakFirstIfNotEmpty ;
344
+
345
+ foreach ($ metadata as $ key => $ value ) {
346
+ if ($ skipSeparator ) {
347
+ $ code [] = sprintf ('%s: %s ' , $ this ->escape ($ key ), $ this ->escape ($ value ));
348
+ $ skipSeparator = false ;
349
+ } else {
350
+ $ code [] = sprintf ('%s%s: %s ' , '<BR/> ' , $ this ->escape ($ key ), $ this ->escape ($ value ));
351
+ }
352
+ }
353
+
354
+ return $ code ? implode ('' , $ code ) : '' ;
355
+ }
272
356
}
0 commit comments