These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more
1 | <?php |
||
2 | /******************************************************************************* |
||
3 | * This file contains the Process Printer for SemanticResultFormats |
||
4 | * (https://www.mediawiki.org/wiki/Extension:Semantic_Result_Formats) |
||
5 | * |
||
6 | * Copyright (c) 2008 - 2009 Frank Dengler and Hans-Jörg Happel |
||
7 | * |
||
8 | * Process Printer is free software: you can redistribute it and/or modify |
||
9 | * it under the terms of the GNU General Public License as published by |
||
10 | * the Free Software Foundation, either version 3 of the License, or |
||
11 | * (at your option) any later version. |
||
12 | * |
||
13 | * Process Printer is distributed in the hope that it will be useful, |
||
14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
||
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
||
16 | * GNU General Public License for more details. |
||
17 | * |
||
18 | * You should have received a copy of the GNU General Public License |
||
19 | * along with Process Printer. If not, see <http://www.gnu.org/licenses/>. |
||
20 | *******************************************************************************/ |
||
21 | |||
22 | if ( !defined( 'MEDIAWIKI' ) ) { |
||
23 | die( 'Not an entry point.' ); |
||
24 | } |
||
25 | |||
26 | /** |
||
27 | * This is a contribution to Semtantic Result Formats (SRF) which are an |
||
28 | * extension of Semantic MediaWiki (SMW) which in turn is an extension |
||
29 | * of MediaWiki |
||
30 | * |
||
31 | * SRF defines certain "printers" to render the results of SMW semantic |
||
32 | * "ASK"-queries. Some of these printers make use of the GraphViz/dot |
||
33 | * library (which is wrapped by a separate MediaWiki extension). |
||
34 | * |
||
35 | * The purpose of this extension, is to render results of ASK-Queries |
||
36 | * (e.g. Classes with Attributes) as GraphViz-layouted process graphs |
||
37 | * |
||
38 | * |
||
39 | * @author Frank Dengler |
||
40 | * @author Hans-Jörg Happel |
||
41 | * @ingroup SemanticResultFormats |
||
42 | * |
||
43 | * @note AUTOLOADED |
||
44 | */ |
||
45 | |||
46 | // global variable defining picture path |
||
47 | |||
48 | $srfgPicturePath = "formats/graphviz/images/"; |
||
49 | |||
50 | class SRFProcess extends SMWResultPrinter { |
||
51 | |||
52 | // configuration variables |
||
53 | protected $m_graphValidation = false; |
||
54 | protected $m_isDebugSet = false; |
||
55 | protected $m_processCategory = 'Process'; // Category for processes - required for rendering compound nodes |
||
56 | |||
57 | // internal variables |
||
58 | protected $m_process; // process to be rendered |
||
59 | |||
60 | /** |
||
61 | * (non-PHPdoc) |
||
62 | * @see SMWResultPrinter::handleParameters() |
||
63 | */ |
||
64 | protected function handleParameters( array $params, $outputmode ) { |
||
65 | parent::handleParameters( $params, $outputmode ); |
||
66 | |||
67 | // init process graph instance |
||
68 | $this->m_process = new ProcessGraph(); |
||
69 | |||
70 | $this->m_process->setGraphName( trim( $params['graphname'] ) ); |
||
71 | $this->m_process->setGraphSize( trim( $params['graphsize'] ) ); |
||
72 | $this->m_process->setClusterColor( trim( $params['clustercolor'] ) ); |
||
73 | $this->m_process->setRankdir( strtoupper( trim( $params['rankdir'] ) ) ); |
||
74 | $this->m_process->setHighlightNode( trim( $params['highlight'] ) ); |
||
75 | $this->m_process->setHighlightColor( trim( $params['highlightcolor'] ) ); |
||
76 | $this->m_process->setHighlightColor( trim( $params['redlinkcolor'] ) ); |
||
77 | |||
78 | $this->m_process->setShowRoles( $params['showroles'] ); |
||
79 | $this->m_process->setShowStatus( $params['showstatus'] ); |
||
80 | $this->m_process->setShowRessources( $params['showresources'] ); |
||
81 | $this->m_process->setShowDiscussion( $params['showdiscussion'] ); |
||
82 | $this->m_process->setShowRedLinks( $params['showredlinks'] ); |
||
83 | $this->m_process->setShowCompound( $params['showcompound'] ); |
||
84 | |||
85 | $this->m_processCategory = $params['processcat']; |
||
86 | $this->m_isDebugSet = $params['debug']; |
||
87 | $this->m_graphValidation = $params['graphvalidation']; |
||
88 | } |
||
89 | |||
90 | /** |
||
91 | * @see SMWResultPrinter::getParamDefinitions |
||
92 | * |
||
93 | * @since 1.8 |
||
94 | * |
||
95 | * @param $definitions array of IParamDefinition |
||
96 | * |
||
97 | * @return array of IParamDefinition|array |
||
98 | */ |
||
99 | public function getParamDefinitions( array $definitions ) { |
||
100 | $params = parent::getParamDefinitions( $definitions ); |
||
101 | |||
102 | $params['graphname'] = [ |
||
103 | 'default' => '', |
||
104 | 'message' => 'srf-paramdesc-graphname', |
||
105 | ]; |
||
106 | |||
107 | $params['rankdir'] = [ |
||
108 | 'default' => 'TB', |
||
109 | 'message' => 'srf-paramdesc-rankdir', |
||
110 | ]; |
||
111 | |||
112 | $params['graphsize'] = [ |
||
113 | 'default' => '', |
||
114 | 'message' => 'srf-paramdesc-graphsize', |
||
115 | ]; |
||
116 | |||
117 | $params['clustercolor'] = [ |
||
118 | 'default' => 'lightgrey', |
||
119 | 'message' => 'srf-paramdesc-clustercolor', |
||
120 | ]; |
||
121 | |||
122 | $params['highlight'] = [ |
||
123 | 'default' => '', |
||
124 | 'message' => 'srf-paramdesc-highlight', |
||
125 | ]; |
||
126 | |||
127 | $params['highlightcolor'] = [ |
||
128 | 'default' => 'blue', |
||
129 | 'message' => 'srf-paramdesc-highlightcolor', |
||
130 | ]; |
||
131 | |||
132 | $params['redlinkcolor'] = [ |
||
133 | 'default' => 'red', |
||
134 | 'message' => 'srf-paramdesc-redlinkcolor', |
||
135 | ]; |
||
136 | |||
137 | $params['processcat'] = [ |
||
138 | 'default' => 'Process', |
||
139 | 'message' => 'srf-paramdesc-processcategory', |
||
140 | ]; |
||
141 | |||
142 | $params['showroles'] = [ |
||
143 | 'type' => 'boolean', |
||
144 | 'default' => false, |
||
145 | 'message' => 'srf-paramdesc-showroles', |
||
146 | ]; |
||
147 | |||
148 | $params['showstatus'] = [ |
||
149 | 'type' => 'boolean', |
||
150 | 'default' => false, |
||
151 | 'message' => 'srf-paramdesc-showstatus', |
||
152 | ]; |
||
153 | |||
154 | $params['showresources'] = [ |
||
155 | 'type' => 'boolean', |
||
156 | 'default' => false, |
||
157 | 'message' => 'srf-paramdesc-showresources', |
||
158 | ]; |
||
159 | |||
160 | $params['showdiscussion'] = [ |
||
161 | 'type' => 'boolean', |
||
162 | 'default' => false, |
||
163 | 'message' => 'srf-paramdesc-showdiscussion', |
||
164 | ]; |
||
165 | |||
166 | $params['showredlinks'] = [ |
||
167 | 'type' => 'boolean', |
||
168 | 'default' => false, |
||
169 | 'message' => 'srf-paramdesc-showredlinks', |
||
170 | ]; |
||
171 | |||
172 | $params['showcompound'] = [ |
||
173 | 'type' => 'boolean', |
||
174 | 'default' => true, |
||
175 | 'message' => 'srf-paramdesc-showcompound', |
||
176 | ]; |
||
177 | |||
178 | $params['debug'] = [ |
||
179 | 'type' => 'boolean', |
||
180 | 'default' => false, |
||
181 | 'message' => 'srf-paramdesc-debug', |
||
182 | ]; |
||
183 | |||
184 | $params['graphvalidation'] = [ |
||
185 | 'type' => 'boolean', |
||
186 | 'default' => false, |
||
187 | 'message' => 'srf-paramdesc-graphvalidation', |
||
188 | ]; |
||
189 | |||
190 | return $params; |
||
191 | } |
||
192 | |||
193 | /** |
||
194 | * This method renders the result set provided by SMW according to the printer |
||
195 | * |
||
196 | * @param res SMWQueryResult, result set of the ask query provided by SMW |
||
197 | * @param outputmode ? |
||
198 | * |
||
199 | * @return String, rendered HTML output of this printer for the ask-query |
||
200 | * |
||
201 | */ |
||
202 | protected function getResultText( SMWQueryResult $res, $outputmode ) { |
||
203 | if ( !is_callable( 'renderGraphviz' ) ) { |
||
204 | wfWarn( 'The SRF Graph printer needs the GraphViz extension to be installed.' ); |
||
205 | return ''; |
||
206 | } |
||
207 | |||
208 | global $wgContLang; // content language object |
||
209 | |||
210 | // |
||
211 | // GraphViz settings |
||
212 | // |
||
213 | $this->isHTML = true; |
||
214 | |||
215 | // |
||
216 | // Iterate all rows in result set |
||
217 | // |
||
218 | |||
219 | $row = $res->getNext(); // get initial row (i.e. array of SMWResultArray) |
||
220 | |||
221 | while ( $row !== false ) { |
||
222 | /* SMWDataItem */ |
||
223 | $subject = $row[0]->getResultSubject(); // get Subject of the Result |
||
224 | // creates a new node if $val has type wikipage |
||
225 | if ( $subject->getDIType() == SMWDataItem::TYPE_WIKIPAGE ) { |
||
226 | $wikiPageValue = new SMWWikiPageValue( '_wpg' ); |
||
227 | $wikiPageValue->setDataItem( $subject ); |
||
228 | $node = $this->m_process->makeNode( |
||
229 | $wikiPageValue->getShortWikiText(), |
||
230 | $wikiPageValue->getShortWikiText() |
||
231 | ); |
||
232 | } |
||
233 | |||
234 | // |
||
235 | // Iterate all colums of the row (which describe properties of the proces node) |
||
236 | // |
||
237 | |||
238 | // FIXME: this does not work with SMW >= 1.6, see |
||
239 | // https://bugzilla.wikimedia.org/show_bug.cgi?id=35003 |
||
240 | |||
241 | // FIXME: got _a bit_ of redundancy here looks like... :/ |
||
242 | |||
243 | /** |
||
244 | * @var SMWResultArray $field |
||
245 | */ |
||
246 | foreach ( $row as $field ) { |
||
247 | |||
248 | // check column title |
||
249 | $req = $field->getPrintRequest(); |
||
250 | switch ( ( strtolower( $req->getLabel() ) ) ) { |
||
251 | |||
252 | case strtolower( $wgContLang->getNsText( NS_CATEGORY ) ): |
||
253 | foreach ( $field->getContent() as $value ) { |
||
254 | $wikiPageValue = new SMWWikiPageValue( '_wpg' ); |
||
255 | $wikiPageValue->setDataItem( $value ); |
||
256 | $val = $wikiPageValue->getShortWikiText(); |
||
257 | |||
258 | if ( $val == ( $wgContLang->getNsText( NS_CATEGORY ) . ':' . $this->m_processCategory ) ) { |
||
259 | $node->setAtomic( false ); |
||
260 | } |
||
261 | } |
||
262 | |||
263 | break; |
||
264 | |||
265 | case "haslabel": |
||
266 | $value = current( $field->getContent() ); // save only the first |
||
267 | |||
268 | if ( ( $value !== false ) ) { |
||
269 | $wikiPageValue = new SMWWikiPageValue( '_wpg' ); |
||
270 | $wikiPageValue->setDataItem( $value ); |
||
271 | $val = $wikiPageValue->getLongWikiText(); |
||
272 | |||
273 | if ( $this->m_process->getUseOtherLabels() ) { |
||
0 ignored issues
–
show
|
|||
274 | $val = str_replace( "&", "and", $val ); |
||
275 | $node->setLabel( $val ); |
||
276 | } |
||
277 | } |
||
278 | break; |
||
279 | |||
280 | case "hasrole": |
||
281 | foreach ( $field->getContent() as $value ) { |
||
282 | $wikiPageValue = new SMWWikiPageValue( $field->getPrintRequest()->getTypeID() ); |
||
283 | $wikiPageValue->setDataItem( $value ); |
||
284 | $val = $wikiPageValue->getShortWikiText(); |
||
285 | |||
286 | $role = $this->m_process->makeRole( $val, $val ); |
||
287 | $node->addRole( $role ); |
||
288 | } |
||
289 | break; |
||
290 | |||
291 | case "usesresource": |
||
292 | foreach ( $field->getContent() as $value ) { |
||
293 | $wikiPageValue = new SMWWikiPageValue( $field->getPrintRequest()->getTypeID() ); |
||
294 | $wikiPageValue->setDataItem( $value ); |
||
295 | $val = $wikiPageValue->getShortWikiText(); |
||
296 | |||
297 | $xres = $this->m_process->makeRessource( $val, $val ); |
||
298 | $node->addUsedRessource( $xres ); |
||
299 | } |
||
300 | break; |
||
301 | |||
302 | case "producesresource": |
||
303 | foreach ( $field->getContent() as $value ) { |
||
304 | $wikiPageValue = new SMWWikiPageValue( $field->getPrintRequest()->getTypeID() ); |
||
305 | $wikiPageValue->setDataItem( $value ); |
||
306 | $val = $wikiPageValue->getShortWikiText(); |
||
307 | |||
308 | $xres = $this->m_process->makeRessource( $val, $val ); |
||
309 | $node->addProducedRessource( $xres ); |
||
310 | } |
||
311 | break; |
||
312 | |||
313 | case "hassuccessor": |
||
314 | |||
315 | if ( count( $field->getContent() ) > 1 ) { |
||
316 | |||
317 | // SplitParallel |
||
318 | $edge = new SplitParallelEdge(); |
||
319 | $edge->setFrom( $node ); |
||
320 | foreach ( $field->getContent() as $value ) { |
||
321 | $wikiPageValue = new SMWWikiPageValue( $field->getPrintRequest()->getTypeID() ); |
||
322 | $wikiPageValue->setDataItem( $value ); |
||
323 | $val = $wikiPageValue->getShortWikiText(); |
||
324 | |||
325 | $edge->addTo( $this->m_process->makeNode( $val, $val ) ); |
||
326 | } |
||
327 | |||
328 | } else { |
||
329 | |||
330 | // Sequence |
||
331 | foreach ( $field->getContent() as $value ) { |
||
332 | $wikiPageValue = new SMWWikiPageValue( $field->getPrintRequest()->getTypeID() ); |
||
333 | $wikiPageValue->setDataItem( $value ); |
||
334 | $val = $wikiPageValue->getShortWikiText(); |
||
335 | |||
336 | $edge = new SequentialEdge(); |
||
337 | $edge->setFrom( $node ); |
||
338 | $edge->setTo( $this->m_process->makeNode( $val, $val ) ); |
||
339 | } |
||
340 | } |
||
341 | |||
342 | break; |
||
343 | |||
344 | case "hasorsuccessor": |
||
345 | |||
346 | if ( count( $field->getContent() ) > 0 ) { |
||
347 | |||
348 | // SplitExclusiveOr |
||
349 | $edge = new SplitExclusiveOrEdge(); |
||
350 | $edge->setFrom( $node ); |
||
351 | foreach ( $field->getContent() as $value ) { |
||
352 | $wikiPageValue = new SMWWikiPageValue( $field->getPrintRequest()->getTypeID() ); |
||
353 | $wikiPageValue->setDataItem( $value ); |
||
354 | $val = $wikiPageValue->getShortWikiText(); |
||
355 | |||
356 | $edge->addTo( $this->m_process->makeNode( $val, $val ) ); |
||
357 | } |
||
358 | } |
||
359 | |||
360 | break; |
||
361 | |||
362 | case "hascontruesuccessor": |
||
363 | |||
364 | if ( count( $field->getContent() ) > 0 ) { |
||
365 | |||
366 | // SplitConditional |
||
367 | if ( !isset( $cond_edge ) ) { |
||
368 | $cond_edge = new SplitConditionalOrEdge(); |
||
369 | $cond_edge->setFrom( $node ); |
||
370 | } |
||
371 | |||
372 | // should be only one |
||
373 | foreach ( $field->getContent() as $value ) { |
||
374 | $wikiPageValue = new SMWWikiPageValue( $field->getPrintRequest()->getTypeID() ); |
||
375 | $wikiPageValue->setDataItem( $value ); |
||
376 | $val = $wikiPageValue->getShortWikiText(); |
||
377 | |||
378 | $cond_edge->setToTrue( $this->m_process->makeNode( $val, $val ) ); |
||
379 | } |
||
380 | |||
381 | } |
||
382 | |||
383 | break; |
||
384 | |||
385 | case "hasconfalsesuccessor": |
||
386 | |||
387 | if ( count( $field->getContent() ) > 0 ) { |
||
388 | |||
389 | // SplitConditional |
||
390 | if ( !isset( $cond_edge ) ) { |
||
391 | $cond_edge = new SplitConditionalOrEdge(); |
||
392 | $cond_edge->setFrom( $node ); |
||
393 | } |
||
394 | |||
395 | // should be only one |
||
396 | foreach ( $field->getContent() as $value ) { |
||
397 | $wikiPageValue = new SMWWikiPageValue( $field->getPrintRequest()->getTypeID() ); |
||
398 | $wikiPageValue->setDataItem( $value ); |
||
399 | $val = $wikiPageValue->getShortWikiText(); |
||
400 | |||
401 | $cond_edge->setToFalse( $this->m_process->makeNode( $val, $val ) ); |
||
402 | } |
||
403 | } |
||
404 | |||
405 | break; |
||
406 | |||
407 | case "hascondition": |
||
408 | |||
409 | if ( count( $field->getContent() ) > 0 ) { |
||
410 | |||
411 | // SplitConditional |
||
412 | if ( !isset( $cond_edge ) ) { |
||
413 | $cond_edge = new SplitConditionalOrEdge(); |
||
414 | $cond_edge->setFrom( $node ); |
||
415 | } |
||
416 | |||
417 | // should be only one |
||
418 | foreach ( $field->getContent() as $value ) { |
||
419 | $wikiPageValue = new SMWWikiPageValue( $field->getPrintRequest()->getTypeID() ); |
||
420 | $wikiPageValue->setDataItem( $value ); |
||
421 | $val = $wikiPageValue->getShortWikiText(); |
||
422 | |||
423 | $cond_edge->setConditionText( $val ); |
||
424 | |||
425 | } |
||
426 | } |
||
427 | |||
428 | break; |
||
429 | |||
430 | case "hasstatus": |
||
431 | |||
432 | // should be only one |
||
433 | foreach ( $field->getContent() as $value ) { |
||
434 | $wikiPageValue = new SMWWikiPageValue( $field->getPrintRequest()->getTypeID() ); |
||
435 | $wikiPageValue->setDataItem( $value ); |
||
436 | $val = $wikiPageValue->getShortWikiText(); |
||
437 | |||
438 | $node->setStatus( $val ); |
||
439 | } |
||
440 | |||
441 | break; |
||
442 | |||
443 | default: |
||
444 | |||
445 | // TODO - redundant column in result |
||
446 | |||
447 | } |
||
448 | } |
||
449 | |||
450 | // reset row variables |
||
451 | unset( $node ); |
||
452 | unset( $cond_edge ); |
||
453 | |||
454 | $row = $res->getNext(); // switch to next row |
||
455 | } |
||
456 | |||
457 | // |
||
458 | // generate graphInput |
||
459 | // |
||
460 | $graphInput = $this->m_process->getGraphVizCode(); |
||
461 | |||
462 | // |
||
463 | // render graphViz code |
||
464 | // |
||
465 | $result = renderGraphviz( $graphInput ); |
||
466 | |||
467 | $debug = ''; |
||
468 | if ( $this->m_isDebugSet ) { |
||
469 | $debug = '<pre>' . $graphInput . '</pre>'; |
||
470 | } |
||
471 | |||
472 | return $result . $debug; |
||
473 | } |
||
474 | } |
||
475 | |||
476 | /** |
||
477 | * Class representing a process graph |
||
478 | */ |
||
479 | class ProcessGraph { |
||
480 | |||
481 | // configuration variables |
||
482 | protected $m_graphName = ''; |
||
483 | protected $m_rankdir = 'TB'; |
||
484 | protected $m_graphSize = ''; |
||
485 | protected $m_clusterColor = 'lightgrey'; |
||
486 | protected $m_showStatus = false; // should status be rendered? |
||
487 | protected $m_showRoles = false; // should roles be rendered? |
||
488 | protected $m_showRessources = false; // should ressources be rendered? |
||
489 | protected $m_showDiscussion = false; // should discussion be rendered? |
||
490 | protected $m_highlightNode = ''; // node to be highlighted |
||
491 | protected $m_highlightColor = 'blue'; // highlight font color |
||
492 | protected $m_showRedLinks = false; // check and highlight red links? |
||
493 | protected $m_redLinkColor = 'red'; // red link font color |
||
494 | protected $m_showCompound = true; // highlight compound nodes (=subprocesses) |
||
495 | |||
496 | public $m_useHtmlNodes = true; // Set to false if you do not want to use HTML table nodes |
||
497 | |||
498 | // instance variables |
||
499 | protected $m_nodes = []; // list of all nodes |
||
500 | protected $m_startnodes = []; // list of start nodes |
||
501 | protected $m_endnodes = []; // list of end nodes |
||
502 | protected $m_ressources = []; // list of ressources |
||
503 | protected $m_roles = []; // list of roles |
||
504 | protected $m_errors = []; // list of errors |
||
505 | |||
506 | /** |
||
507 | * This method should be used for getting new or existing nodes |
||
508 | * If a node does not exist yet, it will be created |
||
509 | * |
||
510 | * @param $id string, node id |
||
511 | * @param $label string, node label |
||
512 | * |
||
513 | * @return Object of type ProcessNode |
||
514 | */ |
||
515 | public function makeNode( $id, $label ) { |
||
516 | // check if node exists |
||
517 | if ( isset( $this->m_nodes[$id] ) ) { |
||
518 | // take existing node |
||
519 | $node = $this->m_nodes[$id]; |
||
520 | |||
521 | } else { |
||
522 | // create new node |
||
523 | |||
524 | $node = new ProcessNode(); |
||
525 | $node->setId( $id ); |
||
526 | $node->setLabel( $label ); |
||
527 | $node->setProcess( $this ); |
||
528 | |||
529 | // is actual node name the same like the one to highlight? |
||
530 | if ( strcasecmp( $id, $this->m_highlightNode ) == 0 ) { |
||
531 | $node->setFontColor( $this->m_highlightColor ); |
||
532 | } |
||
533 | |||
534 | // is the node a red link (i.e. corresponding wiki page does not yet exist)? |
||
535 | if ( $this->m_showRedLinks ) { |
||
536 | $title = Title::newFromDBkey( $id ); |
||
537 | if ( isset( $title ) && ( !$title->exists() ) ) { |
||
538 | $node->setFontColor( $this->m_redLinkColor ); |
||
539 | } |
||
540 | } |
||
541 | |||
542 | // add new node to process |
||
543 | $this->m_nodes[$id] = $node; |
||
544 | } |
||
545 | |||
546 | return $node; |
||
547 | |||
548 | } |
||
549 | |||
550 | public function makeRole( $id, $label ) { |
||
551 | // check if role exists |
||
552 | if ( isset( $this->m_roles[$id] ) ) { |
||
553 | // take existing roles |
||
554 | $role = $this->m_roles[$id]; |
||
555 | |||
556 | } else { |
||
557 | $role = new ProcessRole(); |
||
558 | $role->setId( $id ); |
||
559 | $role->setLabel( $label ); |
||
560 | |||
561 | // add new role to process |
||
562 | $this->m_roles[$id] = $role; |
||
563 | } |
||
564 | |||
565 | return $role; |
||
566 | |||
567 | } |
||
568 | |||
569 | public function makeRessource( $id, $label ) { |
||
570 | // check if res exists |
||
571 | if ( isset( $this->m_ressources[$id] ) ) { |
||
572 | // take existing res |
||
573 | $res = $this->m_ressources[$id]; |
||
574 | |||
575 | } else { |
||
576 | $res = new ProcessRessource(); |
||
577 | $res->setId( $id ); |
||
578 | $res->setLabel( $label ); |
||
579 | |||
580 | // add new res to process |
||
581 | $this->m_ressources[$id] = $res; |
||
582 | |||
583 | } |
||
584 | |||
585 | return $res; |
||
586 | |||
587 | } |
||
588 | |||
589 | public function getEndNodes() { |
||
590 | if ( count( $this->m_endnodes ) == 0 ) { |
||
591 | foreach ( $this->m_nodes as $node ) { |
||
592 | if ( count( $node->getSucc() ) == 0 ) { |
||
593 | $this->m_endnodes[] = $node; |
||
594 | } |
||
595 | } |
||
596 | } |
||
597 | |||
598 | return $this->m_endnodes; |
||
599 | } |
||
600 | |||
601 | public function getStartNodes() { |
||
602 | |||
603 | if ( count( $this->m_startnodes ) == 0 ) { |
||
604 | foreach ( $this->m_nodes as $node ) { |
||
605 | if ( count( $node->getPred() ) == 0 ) { |
||
606 | $this->m_startnodes[] = $node; |
||
607 | } |
||
608 | } |
||
609 | } |
||
610 | |||
611 | return $this->m_startnodes; |
||
612 | } |
||
613 | |||
614 | public function setShowStatus( $show ) { |
||
615 | $this->m_showStatus = $show; |
||
616 | } |
||
617 | |||
618 | public function getShowStatus() { |
||
619 | return $this->m_showStatus; |
||
620 | } |
||
621 | |||
622 | public function setShowRoles( $show ) { |
||
623 | $this->m_showRoles = $show; |
||
624 | } |
||
625 | |||
626 | public function getShowRoles() { |
||
627 | return $this->m_showRoles; |
||
628 | } |
||
629 | |||
630 | public function setShowCompound( $show ) { |
||
631 | $this->m_showCompound = $show; |
||
632 | } |
||
633 | |||
634 | public function getShowCompound() { |
||
635 | return $this->m_showCompound; |
||
636 | } |
||
637 | |||
638 | public function setShowDiscussion( $show ) { |
||
639 | $this->m_showDiscussion = $show; |
||
640 | } |
||
641 | |||
642 | public function getShowDiscussion() { |
||
643 | return $this->m_showDiscussion; |
||
644 | } |
||
645 | |||
646 | public function setShowRessources( $show ) { |
||
647 | $this->m_showRessources = $show; |
||
648 | } |
||
649 | |||
650 | public function getShowRessources() { |
||
651 | return $this->m_showRessources; |
||
652 | } |
||
653 | |||
654 | public function setGraphName( $name ) { |
||
655 | $this->m_graphName = $name; |
||
656 | } |
||
657 | |||
658 | public function getGraphName() { |
||
659 | if ( $this->m_graphName == '' ) { |
||
660 | $this->m_graphName = 'ProcessQueryResult' . rand( 1, 99999 ); |
||
661 | } |
||
662 | return $this->m_graphName; |
||
663 | } |
||
664 | |||
665 | public function setGraphSize( $size ) { |
||
666 | $this->m_graphSize = $size; |
||
667 | } |
||
668 | |||
669 | public function setRankdir( $rankdir ) { |
||
670 | $this->m_rankdir = $rankdir; |
||
671 | } |
||
672 | |||
673 | public function setClusterColor( $color ) { |
||
674 | $this->m_clusterColor = $color; |
||
675 | } |
||
676 | |||
677 | public function setHighlightColor( $color ) { |
||
678 | $this->m_highlightColor = $color; |
||
679 | } |
||
680 | |||
681 | public function setRedLinkColor( $color ) { |
||
682 | $this->m_redLinkColor = $color; |
||
683 | } |
||
684 | |||
685 | public function setShowRedLinks( $show ) { |
||
686 | $this->m_showRedLinks = $show; |
||
687 | } |
||
688 | |||
689 | public function setHighlightNode( $name ) { |
||
690 | $this->m_highlightNode = $name; |
||
691 | } |
||
692 | |||
693 | public function addError( $error ) { |
||
694 | $this->m_errors[] = $error; |
||
695 | } |
||
696 | |||
697 | public function getErrors() { |
||
698 | return $this->m_errors; |
||
699 | } |
||
700 | |||
701 | public function getGraphVizCode() { |
||
702 | // |
||
703 | // header |
||
704 | // |
||
705 | $res = 'digraph ' . $this->getGraphName() . ' { |
||
706 | |||
707 | ranksep="0.5";'; |
||
708 | if ( $this->m_graphSize != '' ) { |
||
709 | $res .= ' |
||
710 | size="' . $this->m_graphSize . '";'; |
||
711 | } |
||
712 | $res .= ' |
||
713 | rankdir=' . $this->m_rankdir . '; |
||
714 | '; |
||
715 | |||
716 | // |
||
717 | // add startnodes |
||
718 | // |
||
719 | // TODO I18N |
||
720 | $res .= ' |
||
721 | {rank=source; "Start";} |
||
722 | "Start"[shape=box,label="Start",style=filled,color=green];'; |
||
723 | |||
724 | foreach ( $this->getStartNodes() as $node ) { |
||
725 | $res .= ' |
||
726 | "Start" -> "' . $node->getId() . '":port1:n;'; |
||
727 | } |
||
728 | |||
729 | $res .= ' |
||
730 | '; |
||
731 | |||
732 | // |
||
733 | // add endnodes |
||
734 | // |
||
735 | // TODO I18N |
||
736 | $res .= ' |
||
737 | {rank=sink; "End"; } |
||
738 | "End"[shape=box,label="End",style=filled,color=green];'; |
||
739 | |||
740 | foreach ( $this->getEndNodes() as $node ) { |
||
741 | $res .= ' |
||
742 | "' . $node->getId() . '":port1:s -> "End";'; |
||
743 | } |
||
744 | |||
745 | $res .= ' |
||
746 | |||
747 | '; |
||
748 | |||
749 | // |
||
750 | // add subnodes |
||
751 | // |
||
752 | foreach ( $this->m_nodes as $node ) { |
||
753 | $res .= $node->getGraphVizCode(); |
||
754 | } |
||
755 | |||
756 | // |
||
757 | // add final stuff |
||
758 | // |
||
759 | $res .= |
||
760 | ' |
||
761 | }'; |
||
762 | |||
763 | return $res; |
||
764 | |||
765 | } |
||
766 | |||
767 | } |
||
768 | |||
769 | abstract class ProcessElement { |
||
770 | |||
771 | // TODO I18N |
||
772 | private $m_id = 'no_id'; |
||
773 | private $m_label = 'unlabeled'; |
||
774 | private $m_uid; |
||
775 | |||
776 | public function getUUID() { |
||
777 | if ( !isset( $this->m_uid ) ) { |
||
778 | $this->m_uid = sprintf( |
||
779 | '%04x%04x-%04x-%04x-%04x-%04x%04x%04x', |
||
780 | mt_rand( 0, 0xffff ), |
||
781 | mt_rand( 0, 0xffff ), |
||
782 | mt_rand( 0, 0xffff ), |
||
783 | mt_rand( 0, 0x0fff ) | 0x4000, |
||
784 | mt_rand( 0, 0x3fff ) | 0x8000, |
||
785 | mt_rand( 0, 0xffff ), |
||
786 | mt_rand( 0, 0xffff ), |
||
787 | mt_rand( 0, 0xffff ) |
||
788 | ); |
||
789 | } |
||
790 | |||
791 | return $this->m_uid; |
||
792 | } |
||
793 | |||
794 | public function getId() { |
||
795 | return $this->m_id; |
||
796 | } |
||
797 | |||
798 | public function setId( $id ) { |
||
799 | $this->m_id = $id; |
||
800 | } |
||
801 | |||
802 | public function getLabel() { |
||
803 | return $this->m_label; |
||
804 | } |
||
805 | |||
806 | public function setLabel( $label ) { |
||
807 | $this->m_label = $label; |
||
808 | } |
||
809 | |||
810 | } |
||
811 | |||
812 | class ProcessRessource extends ProcessElement { |
||
813 | |||
814 | private $m_usedby = []; |
||
815 | private $m_producedby = []; |
||
816 | |||
817 | public function getProducers() { |
||
818 | return $this->m_producedby; |
||
819 | } |
||
820 | |||
821 | public function getUsers() { |
||
822 | return $this->m_usedby; |
||
823 | } |
||
824 | |||
825 | public function addProducer( $node ) { |
||
826 | $this->m_producedby[] = $node; |
||
827 | } |
||
828 | |||
829 | public function addUser( $node ) { |
||
830 | $this->m_usedby[] = $node; |
||
831 | } |
||
832 | |||
833 | } |
||
834 | |||
835 | class ProcessRole extends ProcessElement { |
||
836 | |||
837 | private $m_nodes = []; |
||
838 | |||
839 | public function getNodes() { |
||
840 | return $this->m_nodes; |
||
841 | } |
||
842 | |||
843 | public function addNode( $node ) { |
||
844 | $this->m_nodes[] = $node; |
||
845 | } |
||
846 | |||
847 | } |
||
848 | |||
849 | class ProcessNode extends ProcessElement { |
||
850 | |||
851 | private $m_status; // status value |
||
852 | private $m_is_atomic = true; // set false if this is a compound node |
||
853 | |||
854 | private $m_process; // reference to parent process |
||
855 | |||
856 | private $m_fontColor = ''; // font color to render |
||
857 | |||
858 | private $m_usedressources = []; // ressources used by this node |
||
859 | private $m_producedressources = []; // ressources produces by this node |
||
860 | private $m_roles = []; // roles related to this node |
||
861 | |||
862 | private $m_edgeout; // outgoing edge (can be only one) |
||
863 | private $m_edgesin = []; // incoming edges (can be many) |
||
864 | |||
865 | public function setStatus( $status ) { |
||
866 | $this->m_status = $status; |
||
867 | } |
||
868 | |||
869 | public function getStatus() { |
||
870 | return $this->m_status; |
||
871 | } |
||
872 | |||
873 | public function setFontColor( $color ) { |
||
874 | $this->m_fontColor = $color; |
||
875 | } |
||
876 | |||
877 | public function setProcess( $proc ) { |
||
878 | $this->m_process = $proc; |
||
879 | } |
||
880 | |||
881 | public function getProcess() { |
||
882 | return $this->m_process; |
||
883 | } |
||
884 | |||
885 | public function getPred() { |
||
886 | $res = []; |
||
887 | |||
888 | foreach ( $this->m_edgesin as $edge ) { |
||
889 | $res = array_merge( $res, $edge->getPred() ); |
||
890 | } |
||
891 | |||
892 | return $res; |
||
893 | } |
||
894 | |||
895 | public function getSucc() { |
||
896 | $res = []; |
||
897 | |||
898 | if ( isset( $this->m_edgeout ) ) { |
||
899 | $res = $this->m_edgeout->getSucc(); |
||
900 | } |
||
901 | |||
902 | return $res; |
||
903 | } |
||
904 | |||
905 | public function setEdgeOut( $edge ) { |
||
906 | $this->m_edgeout = $edge; |
||
907 | } |
||
908 | |||
909 | public function getEdgeOut() { |
||
910 | return $this->m_edgeout; |
||
911 | } |
||
912 | |||
913 | public function addEdgeIn( $edge ) { |
||
914 | $this->m_edgesin[] = $edge; |
||
915 | } |
||
916 | |||
917 | public function getEdgesIn() { |
||
918 | return $this->m_edgesin; |
||
919 | } |
||
920 | |||
921 | public function addRole( $role ) { |
||
922 | $this->m_roles[] = $role; |
||
923 | $role->addNode( $this ); |
||
924 | } |
||
925 | |||
926 | public function getRoles() { |
||
927 | return $this->m_roles; |
||
928 | } |
||
929 | |||
930 | public function addUsedRessource( $res ) { |
||
931 | $this->m_usedressources[] = $res; |
||
932 | $res->addUser( $this ); |
||
933 | } |
||
934 | |||
935 | public function getUsedRessources() { |
||
936 | return $this->m_usedressources; |
||
937 | } |
||
938 | |||
939 | public function addProducedRessource( $res ) { |
||
940 | $this->m_producedressources[] = $res; |
||
941 | $res->addProducer( $this ); |
||
942 | } |
||
943 | |||
944 | public function getProducedRessources() { |
||
945 | return $this->m_producedressources; |
||
946 | } |
||
947 | |||
948 | public function isAtomic() { |
||
949 | return $this->m_is_atomic; |
||
950 | } |
||
951 | |||
952 | public function setAtomic( $atomic ) { |
||
953 | $this->m_is_atomic = $atomic; |
||
954 | } |
||
955 | |||
956 | public function getGraphVizCode() { |
||
957 | global $IP, $srfgPicturePath, $srfgIP; |
||
958 | // |
||
959 | // show node status |
||
960 | // |
||
961 | $status = ''; |
||
962 | if ( $this->getProcess()->getShowStatus() ) { |
||
963 | |||
964 | if ( file_exists( $IP . "/images/p000.png" ) ) { |
||
965 | $PicturePath = $IP . "/images/"; |
||
966 | } elseif ( file_exists( $srfgIP . "/formats/graphviz/images/p000.png" ) ) { |
||
967 | $PicturePath = $srfgIP . "/formats/graphviz/images/"; |
||
968 | } else { |
||
969 | $PicturePath = $IP . $srfgPicturePath; |
||
970 | } |
||
971 | // $color = 'grey' . $this->getStatus(); |
||
972 | // $color = 'grey' . rand(1, 100); |
||
973 | // $status = ',style=filled,color=' . $color; |
||
974 | if ( $this->getStatus() != '' ) { |
||
975 | if ( $this->getStatus() < 25 ) { |
||
976 | $status = ' HREF="[[' . $this->getId() . ']]" TOOLTIP="status ' . $this->getStatus( |
||
977 | ) . '%"><IMG SRC="' . $PicturePath . 'p000.png" /'; |
||
978 | } elseif ( $this->getStatus() < 50 ) { |
||
979 | $status = ' HREF="[[' . $this->getId() . ']]" TOOLTIP="status ' . $this->getStatus( |
||
980 | ) . '%"><IMG SRC="' . $PicturePath . 'p025.png" /'; |
||
981 | } elseif ( $this->getStatus() < 75 ) { |
||
982 | $status = ' HREF="[[' . $this->getId() . ']]" TOOLTIP="status ' . $this->getStatus( |
||
983 | ) . '%"><IMG SRC="' . $PicturePath . 'p050.png" /'; |
||
984 | } elseif ( $this->getStatus() < 100 ) { |
||
985 | $status = ' HREF="[[' . $this->getId() . ']]" TOOLTIP="status ' . $this->getStatus( |
||
986 | ) . '%"><IMG SRC="' . $PicturePath . 'p075.png" /'; |
||
987 | } elseif ( $this->getStatus() == 100 ) { |
||
988 | $status = ' HREF="[[' . $this->getId() . ']]" TOOLTIP="status ' . $this->getStatus( |
||
989 | ) . '%"><IMG SRC="' . $PicturePath . 'p100.png" /'; |
||
990 | } |
||
991 | } |
||
992 | |||
993 | } |
||
994 | |||
995 | // |
||
996 | // show discussion page |
||
997 | // |
||
998 | $discussion = ''; |
||
999 | if ( $this->getProcess()->getShowDiscussion() ) { |
||
1000 | |||
1001 | if ( file_exists( $IP . "/images/discuss_icon.png" ) ) { |
||
1002 | $PicturePath = $IP . "/images/"; |
||
1003 | } elseif ( file_exists( $srfgIP . "/formats/graphviz/images/discuss_icon.png" ) ) { |
||
1004 | $PicturePath = $srfgIP . "/formats/graphviz/images/"; |
||
1005 | } else { |
||
1006 | $PicturePath = $IP . $srfgPicturePath; |
||
1007 | } |
||
1008 | $discussionTitle = Title::newFromText( 'Talk:' . $this->getId() . '' ); |
||
1009 | if ( $discussionTitle->isKnown() ) { |
||
1010 | $discussion = ' HREF="[[Talk:' . $this->getId() . ']]" TOOLTIP="Talk:' . $this->getId( |
||
1011 | ) . '"><IMG SRC="' . $PicturePath . 'discuss_icon.png" /'; |
||
1012 | } else { |
||
1013 | $discussion = ' HREF="[[Talk:' . $this->getId() . ']]" TOOLTIP="Talk:' . $this->getId( |
||
1014 | ) . '"><IMG SRC="' . $PicturePath . 'discuss_icon_grey.png" /'; |
||
1015 | } |
||
1016 | |||
1017 | } |
||
1018 | |||
1019 | // use highlight color if set (either CURRENTPAGE or REDLINK highlighting - see ProcessGraph::makeNode() |
||
1020 | $high = ''; |
||
1021 | if ( $this->m_fontColor !== '' ) { |
||
1022 | $high = ',fontcolor=' . $this->m_fontColor; |
||
1023 | } |
||
1024 | |||
1025 | // insert icon for non-atomic nodes (i.e. subprocesses) |
||
1026 | $compound = '<TR><TD ALIGN="LEFT" BORDER="0" WIDTH="20px">'; |
||
1027 | if ( $this->getProcess()->getShowCompound() ) { |
||
1028 | if ( file_exists( $IP . "/images/subprocess.png" ) ) { |
||
1029 | $PicturePath = $IP . "/images/"; |
||
1030 | } elseif ( file_exists( $srfgIP . "/formats/graphviz/images/subprocess.png" ) ) { |
||
1031 | $PicturePath = $srfgIP . "/formats/graphviz/images/"; |
||
1032 | } else { |
||
1033 | $PicturePath = $IP . $srfgPicturePath; |
||
1034 | } |
||
1035 | if ( !$this->isAtomic() ) { |
||
1036 | $compound = '<TR><TD ALIGN="LEFT" BORDER="0" WIDTH="20px" HREF="[[' . $this->getId( |
||
1037 | ) . ']]" TOOLTIP="sub process"><IMG SRC="' . $PicturePath . 'subprocess.png"/>'; |
||
1038 | } |
||
1039 | } |
||
1040 | |||
1041 | // |
||
1042 | // render node itself |
||
1043 | // |
||
1044 | if ( $this->m_process->m_useHtmlNodes ) { |
||
1045 | $res = |
||
1046 | '"' . $this->getId( |
||
1047 | ) . '" [shape=plaintext,label=<<TABLE BORDER="0" CELLBORDER="1" CELLSPACING="0">' . $compound . '</TD><TD BORDER="0" WIDTH="80%"></TD><TD ALIGN="RIGHT" BORDER="0" WIDTH="20px"' . $status . '></TD><TD ALIGN="RIGHT" BORDER="0" WIDTH="20px"' . $discussion . '></TD></TR><TR><TD COLSPAN="4" PORT="port1" HREF="[[' . $this->getId( |
||
1048 | ) . ']]" TOOLTIP="' . $this->getLabel() . '"><FONT' . $high . '>' . $this->getLabel() . '</FONT></TD> </TR></TABLE>>]; |
||
1049 | '; |
||
1050 | } else { |
||
1051 | $res = |
||
1052 | '"' . $this->getId() . '"[label="' . $this->getLabel( |
||
1053 | ) . '",shape=rect, height=1.5, URL="[[' . $this->getId() . ']]"]; |
||
1054 | '; |
||
1055 | } |
||
1056 | |||
1057 | // |
||
1058 | // render outgoing node |
||
1059 | // |
||
1060 | if ( isset( $this->m_edgeout ) ) { |
||
1061 | $res .= $this->m_edgeout->getGraphVizCode(); |
||
1062 | } |
||
1063 | |||
1064 | // |
||
1065 | // show cluster for roles and ressources |
||
1066 | // |
||
1067 | $rrcluster = false; |
||
1068 | $rrcode = 'subgraph "cluster_role' . rand( 1, 9999 ) . '" { style=filled;color=lightgrey;'; |
||
1069 | |||
1070 | // show roles |
||
1071 | if ( $this->getProcess()->getShowRoles() ) { |
||
1072 | |||
1073 | foreach ( $this->getRoles() as $role ) { |
||
1074 | $rrcluster = true; |
||
1075 | $rrcode .= ' |
||
1076 | "' . $role->getId() . '"[label="' . $role->getLabel( |
||
1077 | ) . '",shape=doubleoctagon, color=red, URL="[[' . $role->getId() . ']]"]; |
||
1078 | "' . $role->getId() . '" -> "' . $this->getId() . '":port1 [color=red,arrowhead = none,constraint=false]; |
||
1079 | '; |
||
1080 | |||
1081 | } |
||
1082 | } |
||
1083 | |||
1084 | if ( $this->getProcess()->getShowRessources() ) { |
||
1085 | |||
1086 | foreach ( $this->getUsedRessources() as $xres ) { |
||
1087 | $rrcluster = true; |
||
1088 | $rrcode .= ' |
||
1089 | "' . $xres->getId() . '"[label="' . $xres->getLabel( |
||
1090 | ) . '",shape=folder, color=blue, URL="[[' . $xres->getId() . ']]"]; |
||
1091 | "' . $xres->getId() . '" -> "' . $this->getId() . '":port1 [color=blue,constraint=false]; |
||
1092 | '; |
||
1093 | } |
||
1094 | |||
1095 | foreach ( $this->getProducedRessources() as $xres ) { |
||
1096 | $rrcluster = true; |
||
1097 | $rrcode .= ' |
||
1098 | "' . $xres->getId() . '"[label="' . $xres->getLabel( |
||
1099 | ) . '",shape=folder, color=blue, URL="[[' . $xres->getId() . ']]"]; |
||
1100 | "' . $this->getId() . '":port1 -> "' . $xres->getId() . '" [color=blue,constraint=false]; |
||
1101 | '; |
||
1102 | } |
||
1103 | |||
1104 | } |
||
1105 | |||
1106 | if ( $rrcluster ) { |
||
1107 | $res .= $rrcode . '}'; |
||
1108 | } |
||
1109 | |||
1110 | $res .= ' |
||
1111 | '; |
||
1112 | |||
1113 | return $res; |
||
1114 | } |
||
1115 | |||
1116 | } |
||
1117 | |||
1118 | /** |
||
1119 | * Abstract base class for edges in a process graph |
||
1120 | */ |
||
1121 | abstract class ProcessEdge { |
||
1122 | |||
1123 | private $m_id; |
||
1124 | private $m_uid; |
||
1125 | |||
1126 | public function getId() { |
||
1127 | if ( !isset( $this->m_id ) ) { |
||
1128 | $this->m_id = 'edge' . rand( 1, 99999 ); |
||
1129 | } |
||
1130 | |||
1131 | return $this->m_id; |
||
1132 | } |
||
1133 | |||
1134 | public function getUUID() { |
||
1135 | if ( !isset( $this->m_uid ) ) { |
||
1136 | $this->m_uid = sprintf( |
||
1137 | '%04x%04x-%04x-%04x-%04x-%04x%04x%04x', |
||
1138 | mt_rand( 0, 0xffff ), |
||
1139 | mt_rand( 0, 0xffff ), |
||
1140 | mt_rand( 0, 0xffff ), |
||
1141 | mt_rand( 0, 0x0fff ) | 0x4000, |
||
1142 | mt_rand( 0, 0x3fff ) | 0x8000, |
||
1143 | mt_rand( 0, 0xffff ), |
||
1144 | mt_rand( 0, 0xffff ), |
||
1145 | mt_rand( 0, 0xffff ) |
||
1146 | ); |
||
1147 | } |
||
1148 | |||
1149 | return $this->m_uid; |
||
1150 | } |
||
1151 | |||
1152 | abstract public function getSucc(); |
||
1153 | |||
1154 | abstract public function getPred(); |
||
1155 | |||
1156 | abstract public function getGraphVizCode(); |
||
1157 | } |
||
1158 | |||
1159 | abstract class SplitEdge extends ProcessEdge { |
||
1160 | |||
1161 | protected $m_from; |
||
1162 | protected $m_to = []; |
||
1163 | |||
1164 | public function setFrom( $node ) { |
||
1165 | $this->m_from = $node; |
||
1166 | $node->setEdgeOut( $this ); |
||
1167 | } |
||
1168 | |||
1169 | public function addTo( $node ) { |
||
1170 | $this->m_to[] = $node; |
||
1171 | $node->addEdgeIn( $this ); |
||
1172 | } |
||
1173 | |||
1174 | public function getPred() { |
||
1175 | return [ $this->m_from ]; |
||
1176 | } |
||
1177 | |||
1178 | public function getSucc() { |
||
1179 | return $this->m_to; |
||
1180 | } |
||
1181 | |||
1182 | } |
||
1183 | |||
1184 | class SplitConditionalOrEdge extends ProcessEdge { |
||
1185 | |||
1186 | protected $m_from; |
||
1187 | protected $m_to_true; |
||
1188 | protected $m_to_false; |
||
1189 | protected $m_con_text = 'empty_condition'; |
||
1190 | |||
1191 | public function getSucc() { |
||
1192 | return [ $this->m_to_false, $this->m_to_true ]; |
||
1193 | } |
||
1194 | |||
1195 | public function getPred() { |
||
1196 | return [ $this->m_from ]; |
||
1197 | } |
||
1198 | |||
1199 | public function setFrom( $node ) { |
||
1200 | $this->m_from = $node; |
||
1201 | $node->setEdgeOut( $this ); |
||
1202 | } |
||
1203 | |||
1204 | public function setToFalse( $node ) { |
||
1205 | $this->m_to_false = $node; |
||
1206 | $node->addEdgeIn( $this ); |
||
1207 | } |
||
1208 | |||
1209 | public function setToTrue( $node ) { |
||
1210 | $this->m_to_true = $node; |
||
1211 | $node->addEdgeIn( $this ); |
||
1212 | } |
||
1213 | |||
1214 | public function setConditionText( $cond ) { |
||
1215 | $this->m_con_text = $cond; |
||
1216 | } |
||
1217 | |||
1218 | public function getGraphVizCode() { |
||
1219 | |||
1220 | $p = $this->m_from; |
||
1221 | |||
1222 | if ( ( !isset( $this->m_from ) ) || ( !isset( $this->m_to_false ) ) || ( !isset( $this->m_to_true ) ) ) { |
||
1223 | |||
1224 | echo "error with SplitConditionalOrEdge"; // TODO |
||
1225 | exit; |
||
1226 | } |
||
1227 | |||
1228 | $res = |
||
1229 | 'subgraph "clus_' . $this->getId() . '" { |
||
1230 | '; |
||
1231 | |||
1232 | // cond-Shape |
||
1233 | $con = 'con' . rand( 1, 99999 ); |
||
1234 | $res .= |
||
1235 | '"' . $con . '"[shape=diamond,label="' . $this->m_con_text . '",style=filled,color=skyblue]; |
||
1236 | "' . $p->getId() . '":port1:s -> "' . $con . '"; |
||
1237 | '; |
||
1238 | |||
1239 | // True Succ |
||
1240 | $res .= |
||
1241 | '"' . $this->m_to_true->getId() . '" [URL = "[[' . $this->m_to_true->getId() . ']]"]; |
||
1242 | '; |
||
1243 | |||
1244 | $res .= |
||
1245 | '"' . $con . '" -> "' . $this->m_to_true->getId() . '":port1:n [label="true"]; |
||
1246 | '; |
||
1247 | |||
1248 | // False Succ |
||
1249 | $res .= |
||
1250 | '"' . $this->m_to_false->getId() . '" [URL = "[[' . $this->m_to_false->getId() . ']]"]; |
||
1251 | '; |
||
1252 | |||
1253 | $res .= |
||
1254 | '"' . $con . '" -> "' . $this->m_to_false->getId() . '":port1:n [label="false"];'; |
||
1255 | |||
1256 | $res .= ' |
||
1257 | } |
||
1258 | '; |
||
1259 | |||
1260 | return $res; |
||
1261 | } |
||
1262 | |||
1263 | } |
||
1264 | |||
1265 | class SplitExclusiveOrEdge extends SplitEdge { |
||
1266 | |||
1267 | public function getGraphVizCode() { |
||
1268 | global $srfgShapeStyle; |
||
1269 | $p = $this->getPred(); |
||
1270 | $p = $p[0]; |
||
1271 | if ( $srfgShapeStyle == '' ) { |
||
1272 | $srfgShapeStyle = "box"; |
||
1273 | } |
||
1274 | $res = |
||
1275 | 'subgraph "clus_' . $this->getId() . '" { |
||
1276 | '; |
||
1277 | |||
1278 | // add OR-Shape |
||
1279 | $orx = 'or' . rand( 1, 99999 ); |
||
1280 | $res .= |
||
1281 | '"' . $orx . '"[shape=' . $srfgShapeStyle . ',label="+",style=filled,color=gold]; |
||
1282 | "' . $p->getId() . '":port1:s -> "' . $orx . '"; |
||
1283 | '; |
||
1284 | |||
1285 | foreach ( $this->getSucc() as $s ) { |
||
1286 | $res .= |
||
1287 | '"' . $s->getId() . '" [URL="[[' . $s->getId() . ']]"]; |
||
1288 | '; |
||
1289 | |||
1290 | $res .= |
||
1291 | '"' . $orx . '" -> "' . $s->getId() . '":port1:n; |
||
1292 | '; |
||
1293 | } |
||
1294 | |||
1295 | $res .= ' |
||
1296 | } |
||
1297 | '; |
||
1298 | |||
1299 | return $res; |
||
1300 | } |
||
1301 | |||
1302 | } |
||
1303 | |||
1304 | class SplitParallelEdge extends SplitEdge { |
||
1305 | |||
1306 | public function getGraphVizCode() { |
||
1307 | global $srfgShapeStyle; |
||
1308 | if ( $srfgShapeStyle == '' ) { |
||
1309 | $srfgShapeStyle = "box"; |
||
1310 | } |
||
1311 | $p = $this->getPred(); |
||
1312 | $p = $p[0]; |
||
1313 | |||
1314 | $res = |
||
1315 | 'subgraph "clus_' . $this->getId() . '" { |
||
1316 | '; |
||
1317 | |||
1318 | // add AND-Shape |
||
1319 | $and = 'and' . rand( 1, 99999 ); |
||
1320 | $res .= |
||
1321 | '"' . $and . '"[shape=' . $srfgShapeStyle . ',label="||",style=filled,color=palegreen]; |
||
1322 | "' . $p->getId() . '":port1:s -> "' . $and . '"; |
||
1323 | '; |
||
1324 | |||
1325 | foreach ( $this->getSucc() as $s ) { |
||
1326 | $res .= |
||
1327 | '"' . $s->getId() . '" [URL = "[[' . $s->getId() . ']]"]; |
||
1328 | '; |
||
1329 | |||
1330 | $res .= |
||
1331 | '"' . $and . '" -> "' . $s->getId() . '":port1:n; |
||
1332 | '; |
||
1333 | } |
||
1334 | |||
1335 | $res .= ' |
||
1336 | } |
||
1337 | '; |
||
1338 | |||
1339 | return $res; |
||
1340 | } |
||
1341 | |||
1342 | } |
||
1343 | |||
1344 | class SequentialEdge extends ProcessEdge { |
||
1345 | |||
1346 | private $m_from; |
||
1347 | private $m_to; |
||
1348 | |||
1349 | public function setFrom( $node ) { |
||
1350 | $this->m_from = $node; |
||
1351 | $node->setEdgeOut( $this ); |
||
1352 | } |
||
1353 | |||
1354 | public function setTo( $node ) { |
||
1355 | $this->m_to = $node; |
||
1356 | $node->addEdgeIn( $this ); |
||
1357 | } |
||
1358 | |||
1359 | public function getPred() { |
||
1360 | return [ $this->m_from ]; |
||
1361 | } |
||
1362 | |||
1363 | public function getSucc() { |
||
1364 | return [ $this->m_to ]; |
||
1365 | } |
||
1366 | |||
1367 | public function getGraphVizCode() { |
||
1368 | |||
1369 | $p = $this->m_from; |
||
1370 | $s = $this->m_to; |
||
1371 | |||
1372 | $res = |
||
1373 | 'subgraph "clus_' . $this->getId() . '" { |
||
1374 | '; |
||
1375 | |||
1376 | $res .= |
||
1377 | '"' . $s->getId() . '" [URL = "[[' . $s->getId() . ']]"]; |
||
1378 | '; |
||
1379 | |||
1380 | $res .= |
||
1381 | '"' . $p->getId() . '":port1:s -> "' . $s->getId() . '":port1:n;'; |
||
1382 | |||
1383 | $res .= ' |
||
1384 | } |
||
1385 | '; |
||
1386 | |||
1387 | return $res; |
||
1388 | } |
||
1389 | |||
1390 | } |
This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.
This is most likely a typographical error or the method has been renamed.