示例#1
0
 public static function loadString($data_string, $options = array(), $filename = null)
 {
     // Options
     $graphml_group_name = isset($options['group']) ? $options['group'] : null;
     // Graph
     $keys = array();
     $nodes = array();
     $edges = array();
     // Load GraphML into DOM
     $dom = new \DOMDocument();
     $dom->loadXml($data_string);
     // Prepare XPath query engine
     $xpath = new \DOMXpath($dom);
     $xpath->registerNameSpace('g', 'http://graphml.graphdrawing.org/xmlns');
     // Find group node
     if ($graphml_group_name) {
         $root_graph = null;
         foreach ($xpath->query('//g:graph') as $el) {
             foreach ($xpath->query('../g:data/*/*/y:GroupNode/y:NodeLabel', $el) as $label_el) {
                 $label = trim($label_el->textContent);
                 if ($label == $graphml_group_name) {
                     $root_graph = $el;
                     break 2;
                 }
             }
         }
     } else {
         $root_graph = $xpath->query('/g:graphml/g:graph')->item(0);
     }
     if ($root_graph == null) {
         throw new GraphMLException('Graph node not found.');
     }
     // Load keys
     foreach ($xpath->query('./g:key[@attr.name][@id]') as $el) {
         $id = $el->attributes->getNamedItem('id')->value;
         $name = $el->attributes->getNamedItem('attr.name')->value;
         //debug_msg("tag> %s => %s", $id, $name);
         $keys[$id] = $name;
     }
     // Load graph properties
     $graph_props = array();
     foreach ($xpath->query('./g:data[@key]', $root_graph) as $data_el) {
         $k = $data_el->attributes->getNamedItem('key')->value;
         if (isset($keys[$k])) {
             if ($keys[$k] == 'Properties') {
                 // Special handling of machine properties
                 $properties = array();
                 foreach ($xpath->query('./property[@name]', $data_el) as $property_el) {
                     $property_name = $property_el->attributes->getNamedItem('name')->value;
                     foreach ($property_el->attributes as $property_attr_name => $property_attr) {
                         $properties[$property_name][$property_attr_name] = $property_attr->value;
                     }
                 }
                 $graph_props['properties'] = $properties;
             } else {
                 $graph_props[static::str2key($keys[$k])] = trim($data_el->textContent);
             }
         }
     }
     //debug_dump($graph_props, '$graph_props');
     // Load nodes
     foreach ($xpath->query('.//g:node[@id]', $root_graph) as $el) {
         $id = $el->attributes->getNamedItem('id')->value;
         $node_props = array();
         foreach ($xpath->query('.//g:data[@key]', $el) as $data_el) {
             $k = $data_el->attributes->getNamedItem('key')->value;
             if (isset($keys[$k])) {
                 $node_props[static::str2key($keys[$k])] = $data_el->textContent;
             }
         }
         $label = $xpath->query('.//y:NodeLabel', $el)->item(0)->textContent;
         if ($label !== null) {
             $node_props['label'] = trim($label);
         }
         $color = $xpath->query('.//y:Fill', $el)->item(0)->attributes->getNamedItem('color')->value;
         if ($color !== null) {
             $node_props['color'] = trim($color);
         }
         //debug_msg("node> %s: \"%s\"", $id, @ $node_props['state']);
         //debug_dump($node_props, '$node_props');
         $nodes[$id] = $node_props;
     }
     // Load edges
     foreach ($xpath->query('//g:graph/g:edge[@id][@source][@target]') as $el) {
         $id = $el->attributes->getNamedItem('id')->value;
         $source = $el->attributes->getNamedItem('source')->value;
         $target = $el->attributes->getNamedItem('target')->value;
         if (!isset($nodes[$source]) || !isset($nodes[$target])) {
             continue;
         }
         $edge_props = array();
         foreach ($xpath->query('.//g:data[@key]', $el) as $data_el) {
             $k = $data_el->attributes->getNamedItem('key')->value;
             if (isset($keys[$k])) {
                 $edge_props[static::str2key($keys[$k])] = $data_el->textContent;
             }
         }
         $label_query_result = $xpath->query('.//y:EdgeLabel', $el)->item(0);
         if (!$label_query_result) {
             throw new GraphMLException(sprintf('Missing edge label. Edge: %s -> %s', isset($nodes[$source]['label']) ? $nodes[$source]['label'] : $source, isset($nodes[$target]['label']) ? $nodes[$target]['label'] : $target));
         }
         $label = $label_query_result->textContent;
         if ($label !== null) {
             $edge_props['label'] = trim($label);
         }
         $color_query_result = $xpath->query('.//y:LineStyle', $el)->item(0);
         if ($color_query_result) {
             $color = $color_query_result->attributes->getNamedItem('color')->value;
             if ($color !== null) {
                 $edge_props['color'] = trim($color);
             }
         }
         //debug_msg("edge> %s: %s -> %s", $id, $source, $target);
         //debug_dump($edge_props, '$edge_props');
         $edges[$id] = array($source, $target, $edge_props);
     }
     // Build machine definition
     $machine = array('_' => "<?php printf('_%c%c}%c',34,10,10);__halt_compiler();?>");
     // Graph properties
     foreach ($graph_props as $k => $v) {
         $machine[$k] = $v;
     }
     // Store states
     foreach ($nodes as &$n) {
         if (empty($n['state'])) {
             if (empty($n['label'])) {
                 // Skip 'nonexistent' state, it is present by default
                 $n['state'] = '';
                 continue;
             } else {
                 // Use label as state name
                 $n['state'] = (string) $n['label'];
             }
         }
         if (empty($n['label'])) {
             $n['label'] = $n['state'];
         }
         $machine['states'][(string) $n['state']] = $n;
     }
     // Store actions and transitions
     foreach ($edges as $e) {
         list($source_id, $target_id, $props) = $e;
         $source = $source_id != '' ? isset($nodes[$source_id]) ? (string) $nodes[$source_id]['state'] : null : '';
         $target = $target_id != '' ? isset($nodes[$target_id]) ? (string) $nodes[$target_id]['state'] : null : '';
         if ($source === null || $target === null) {
             // Ignore nonexistent nodes
             continue;
         }
         if (@$props['action'] != '') {
             $action = $props['action'];
         } else {
             if (@$props['label'] != '') {
                 $action = $props['label'];
             } else {
                 throw new GraphMLException(sprintf('Missing label at edge "%s" -> "%s".', $nodes[$source]['label'], $nodes[$target]['label']));
             }
         }
         $tr =& $machine['actions'][$action]['transitions'][$source];
         foreach ($props as $k => $v) {
             $tr[$k] = $v;
         }
         $tr['targets'][] = $target;
         unset($tr);
     }
     // Sort stuff to keep them in order when file is modified
     asort($machine['states']);
     asort($machine['actions']);
     //debug_dump($machine['states'], 'States');
     //debug_dump($machine['actions'], 'Actions');
     //debug_dump($machine, '$machine');
     return $machine;
 }
示例#2
0
文件: cortex_xml.php 项目: phpbb/mpv
 /**
  * Execute an XPath query and return the resulting elements
  *
  * @access	public
  * @param	string		XPath
  * @param	bool		Return only the first result
  * @return	mixed		Array if !$return_first, cortex_xml object or null
  */
 public function get_xpath($path, $return_first = false)
 {
     $xpath = new DOMXpath($this->document);
     // Take care of the default namespace, DOMXpath doesn't support this
     if (!is_null($this->default_ns)) {
         $path = preg_replace('#/([^:/]+?)#', '/doc-ns:$1', $path);
         $xpath->registerNameSpace('doc-ns', $this->default_ns);
     }
     $nodes = $this->parse_children($xpath->query($path));
     if ($return_first) {
         return sizeof($nodes) > 0 ? $nodes[0] : null;
     }
     return $nodes;
 }
示例#3
0
 public static function loadString($data_string, $options = [], $filename = null)
 {
     // Options
     $bpmn_process_id = isset($options['process_id']) ? $options['process_id'] : null;
     $state_machine_participant_id = isset($options['state_machine_participant_id']) ? $options['state_machine_participant_id'] : null;
     // Load GraphML into DOM
     $dom = new \DOMDocument();
     $dom->loadXml($data_string);
     // Prepare XPath query engine
     $xpath = new \DOMXpath($dom);
     $xpath->registerNameSpace('bpmn', 'http://www.omg.org/spec/BPMN/20100524/MODEL');
     if ($bpmn_process_id) {
         if (!preg_match('/^[a-zA-Z0-9_.-]*$/', $bpmn_process_id)) {
             throw new BpmnException('Invalid process ID (only alphanumeric characters, underscore, dot and dash are allowed): ' . var_export($bpmn_process_id, true));
         }
         $machine_process_element = $xpath->query('/bpmn:definitions/bpmn:process[@id=\'' . $bpmn_process_id . '\']')->item(0);
     } else {
         $machine_process_element = $xpath->query('/bpmn:definitions/bpmn:process')->item(0);
     }
     // Process element is mandatory
     if (!$machine_process_element) {
         throw new BpmnException('Process element not found: ' . var_export($bpmn_process_id, true));
     }
     // Lets collect arrows, events and tasks (still in BPMN semantics)
     $arrows = [];
     $nodes = [];
     $groups = [];
     // Get processes (groups)
     foreach ($xpath->query('//bpmn:process[@id]') as $el) {
         $id = $el->getAttribute('id');
         $name = $el->getAttribute('name');
         $groups[$id] = ['id' => $id, 'name' => $name == '' ? $id : $name, 'nodes' => []];
     }
     // Get arrows
     foreach (['sequenceFlow', 'messageFlow'] as $type) {
         foreach ($xpath->query('//bpmn:' . $type . '[@id][@sourceRef][@targetRef]') as $el) {
             // Arrow properties
             $id = $el->getAttribute('id');
             $name = $el->getAttribute('name');
             $sourceRef = $el->getAttribute('sourceRef');
             $targetRef = $el->getAttribute('targetRef');
             // Get process where the arrow belongs
             $process_element = $el->parentNode;
             if ($process_element && $process_element->tagName == 'bpmn:process') {
                 $process_id = $process_element->getAttribute('id');
             } else {
                 $process_id = null;
             }
             // Store arrow
             $arrows[$id] = ['id' => $id, 'type' => $type, 'source' => $sourceRef, 'target' => $targetRef, 'name' => $name, 'process' => $process_id];
         }
     }
     // Get nodes
     foreach (['participant', 'startEvent', 'task', 'intermediateThrowEvent', 'intermediateCatchEvent', 'endEvent', 'exclusiveGateway', 'parallelGateway', 'inclusiveGateway', 'complexGateway', 'eventBasedGateway'] as $type) {
         foreach ($xpath->query('//bpmn:' . $type . '[@id]') as $el) {
             $id = $el->getAttribute('id');
             $name = $el->getAttribute('name');
             if ($name == '') {
                 $name = $id;
             }
             // Get process where the node belongs
             if ($processRef = $el->getAttribute('processRef')) {
                 $process_id = $processRef;
             } else {
                 if (($process_element = $el->parentNode) && $process_element->tagName == 'bpmn:process') {
                     $process_id = $process_element->getAttribute('id');
                 } else {
                     $process_id = null;
                 }
             }
             if ($process_id) {
                 $groups[$process_id]['nodes'][] = $id;
             }
             $incoming = [];
             foreach ($xpath->query('./bpmn:incoming/text()[1]', $el) as $in) {
                 $incoming[] = $in->wholeText;
             }
             $outgoing = [];
             foreach ($xpath->query('./bpmn:outgoing/text()[1]', $el) as $out) {
                 $outgoing[] = $out->wholeText;
             }
             $nodes[$id] = ['id' => $id, 'name' => $name, 'type' => $type, 'process' => $process_id, 'incoming' => $incoming, 'outgoing' => $outgoing];
         }
     }
     // Store fragment in state machine definition
     return ['bpmn_fragments' => [$filename . '#' . $bpmn_process_id => ['file' => $filename, 'process_id' => $bpmn_process_id, 'state_machine_participant_id' => $state_machine_participant_id, 'arrows' => $arrows, 'nodes' => $nodes, 'groups' => $groups]]];
     ///---------------
     // Dump BPMN fragment
     /*
     		printf("\n<pre>BPMN diagram: %s, %s\n", basename($filename), $bpmn_process_id);
     		printf("  Nodes:\n");
     		foreach ($nodes as $id => $n) {
     			printf("    %s (%s)\n", var_export($n['name'], true), var_export($id, true));
     			foreach ($n['incoming'] as $in) {
     				printf("        In:  %s\n", $in);
     			}
     			foreach ($n['outgoing'] as $out) {
     				printf("        Out: %s\n", $out);
     			}
     		}
     		printf("  Arrows:\n");
     		foreach ($arrows as $id => $a) {
     			printf("    %25s --> %-25s (%s, %s)\n", $a['source'], $a['target'], var_export($id, true), var_export($a['name'], true));
     		}
     		printf("</pre>\n");
     		// */
 }