@@ -44,23 +44,27 @@ class GraphvizDumper implements DumperInterface
4444 */
4545public function dump (Definition $ definition ,Marking $ marking =null ,array $ options = []):string
4646 {
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 );
4951$ edges =$ this ->findEdges ($ definition );
5052
5153$ options =array_replace_recursive (self ::$ defaultOptions ,$ options );
5254
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 )
5660 .$ this ->addEdges ($ edges )
5761 .$ this ->endDot ();
5862 }
5963
6064/**
6165 * @internal
6266 */
63- protected function findPlaces (Definition $ definition ,Marking $ marking =null ):array
67+ protected function findPlaces (Definition $ definition ,bool $ withMetadata , Marking $ marking =null ):array
6468 {
6569$ workflowMetadata =$ definition ->getMetadataStore ();
6670
@@ -80,9 +84,16 @@ protected function findPlaces(Definition $definition, Marking $marking = null):
8084$ attributes ['style ' ] ='filled ' ;
8185$ attributes ['fillcolor ' ] =$ backgroundColor ;
8286 }
87+ if ($ withMetadata ) {
88+ $ attributes ['metadata ' ] =$ workflowMetadata ->getPlaceMetadata ($ place );
89+ }
8390$ label =$ workflowMetadata ->getMetadata ('label ' ,$ place );
8491if (null !==$ label ) {
8592$ attributes ['name ' ] =$ label ;
93+ if ($ withMetadata ) {
94+ // Don't include label in metadata if already used as name
95+ unset($ attributes ['metadata ' ]['label ' ]);
96+ }
8697 }
8798$ places [$ place ] = [
8899'attributes ' =>$ attributes ,
@@ -95,7 +106,7 @@ protected function findPlaces(Definition $definition, Marking $marking = null):
95106/**
96107 * @internal
97108 */
98- protected function findTransitions (Definition $ definition ):array
109+ protected function findTransitions (Definition $ definition, bool $ withMetadata ):array
99110 {
100111$ workflowMetadata =$ definition ->getMetadataStore ();
101112
@@ -111,9 +122,17 @@ protected function findTransitions(Definition $definition): array
111122 }
112123$ name =$ workflowMetadata ->getMetadata ('label ' ,$ transition ) ??$ transition ->getName ();
113124
125+ if ($ withMetadata ) {
126+ $ metadata =$ workflowMetadata ->getTransitionMetadata ($ transition );
127+ unset($ metadata ['label ' ]);
128+ }else {
129+ $ metadata = [];
130+ }
131+
114132$ transitions [] = [
115133'attributes ' =>$ attributes ,
116134'name ' =>$ name ,
135+ 'metadata ' =>$ metadata ,
117136 ];
118137 }
119138
@@ -123,7 +142,7 @@ protected function findTransitions(Definition $definition): array
123142/**
124143 * @internal
125144 */
126- protected function addPlaces (array $ places ):string
145+ protected function addPlaces (array $ places, float $ withMetadata ):string
127146 {
128147$ code ='' ;
129148
@@ -135,7 +154,15 @@ protected function addPlaces(array $places): string
135154$ placeName =$ id ;
136155 }
137156
138- $ code .=sprintf (" place_%s [label= \"%s \", shape=circle%s]; \n" ,$ this ->dotize ($ id ),$ this ->escape ($ placeName ),$ this ->addAttributes ($ place ['attributes ' ]));
157+ if ($ withMetadata ) {
158+ $ escapedLabel =sprintf ('<<B>%s</B>%s> ' ,$ this ->escape ($ placeName ),$ this ->addMetadata ($ place ['attributes ' ]['metadata ' ]));
159+ // Don't include metadata in default attributes used to format the place
160+ unset($ place ['attributes ' ]['metadata ' ]);
161+ }else {
162+ $ escapedLabel =sprintf ('"%s" ' ,$ this ->escape ($ placeName ));
163+ }
164+
165+ $ code .=sprintf (" place_%s [label=%s, shape=circle%s]; \n" ,$ this ->dotize ($ id ),$ escapedLabel ,$ this ->addAttributes ($ place ['attributes ' ]));
139166 }
140167
141168return $ code ;
@@ -144,12 +171,18 @@ protected function addPlaces(array $places): string
144171/**
145172 * @internal
146173 */
147- protected function addTransitions (array $ transitions ):string
174+ protected function addTransitions (array $ transitions, bool $ withMetadata ):string
148175 {
149176$ code ='' ;
150177
151178foreach ($ transitionsas $ i =>$ place ) {
152- $ code .=sprintf (" transition_%s [label= \"%s \",%s]; \n" ,$ this ->dotize ($ i ),$ this ->escape ($ place ['name ' ]),$ this ->addAttributes ($ place ['attributes ' ]));
179+ if ($ withMetadata ) {
180+ $ escapedLabel =sprintf ('<<B>%s</B>%s> ' ,$ this ->escape ($ place ['name ' ]),$ this ->addMetadata ($ place ['metadata ' ]));
181+ }else {
182+ $ escapedLabel ='" ' .$ this ->escape ($ place ['name ' ]).'" ' ;
183+ }
184+
185+ $ code .=sprintf (" transition_%s [label=%s,%s]; \n" ,$ this ->dotize ($ i ),$ escapedLabel ,$ this ->addAttributes ($ place ['attributes ' ]));
153186 }
154187
155188return $ code ;
@@ -215,10 +248,11 @@ protected function addEdges(array $edges): string
215248/**
216249 * @internal
217250 */
218- protected function startDot (array $ options ):string
251+ protected function startDot (array $ options, string $ label ):string
219252 {
220- return sprintf ("digraph workflow { \n %s \n node [%s]; \n edge [%s]; \n\n" ,
253+ return sprintf ("digraph workflow { \n %s%s \n node [%s]; \n edge [%s]; \n\n" ,
221254$ this ->addOptions ($ options ['graph ' ]),
255+ '"" ' !==$ label &&'<> ' !==$ label ?sprintf (' label=%s ' ,$ label ) :'' ,
222256$ this ->addOptions ($ options ['node ' ]),
223257$ this ->addOptions ($ options ['edge ' ])
224258 );
@@ -248,6 +282,9 @@ protected function escape(string|bool $value): string
248282return \is_bool ($ value ) ? ($ value ?'1 ' :'0 ' ) :addslashes ($ value );
249283 }
250284
285+ /**
286+ * @internal
287+ */
251288protected function addAttributes (array $ attributes ):string
252289 {
253290$ code = [];
@@ -259,6 +296,34 @@ protected function addAttributes(array $attributes): string
259296return $ code ?' ' .implode (' ' ,$ code ) :'' ;
260297 }
261298
299+
300+ /**
301+ * Handles the label of the graph depending on whether a label was set in CLI,
302+ * if metadata should be included and if there are any.
303+ *
304+ * The produced label must be escaped.
305+ *
306+ * @internal
307+ */
308+ protected function formatLabel (Definition $ definition ,string $ withMetadata ,array $ options ):string
309+ {
310+ $ currentLabel =$ options ['label ' ] ??'' ;
311+
312+ if (!$ withMetadata ) {
313+ // Only currentLabel to handle. If null, will be translated to empty string
314+ return sprintf ('"%s" ' ,$ this ->escape ($ currentLabel ));
315+ }
316+ $ workflowMetadata =$ definition ->getMetadataStore ()->getWorkflowMetadata ();
317+
318+ if ('' ===$ currentLabel ) {
319+ // Only metadata to handle
320+ return sprintf ('<%s> ' ,$ this ->addMetadata ($ workflowMetadata ,false ));
321+ }
322+
323+ // currentLabel and metadata to handle
324+ return sprintf ('<<B>%s</B>%s> ' ,$ this ->escape ($ currentLabel ),$ this ->addMetadata ($ workflowMetadata ));
325+ }
326+
262327private function addOptions (array $ options ):string
263328 {
264329$ code = [];
@@ -269,4 +334,25 @@ private function addOptions(array $options): string
269334
270335return implode (' ' ,$ code );
271336 }
337+
338+ /**
339+ * @param bool $lineBreakFirstIfNotEmpty Whether to add a separator in the first place when metadata is not empty
340+ */
341+ private function addMetadata (array $ metadata ,bool $ lineBreakFirstIfNotEmpty =true ):string
342+ {
343+ $ code = [];
344+
345+ $ skipSeparator = !$ lineBreakFirstIfNotEmpty ;
346+
347+ foreach ($ metadataas $ key =>$ value ) {
348+ if ($ skipSeparator ) {
349+ $ code [] =sprintf ('%s: %s ' ,$ this ->escape ($ key ),$ this ->escape ($ value ));
350+ $ skipSeparator =false ;
351+ }else {
352+ $ code [] =sprintf ('%s%s: %s ' ,'<BR/> ' ,$ this ->escape ($ key ),$ this ->escape ($ value ));
353+ }
354+ }
355+
356+ return $ code ?implode ('' ,$ code ) :'' ;
357+ }
272358}