flowList = $flowchart['flowList']; $this->flowInfo = array( 'flowName' => $flowchart['flowName'], 'systemId' => $flowchart['systemId'], 'flowId' => $flowchart['flowId'], 'version' => $flowchart['version'] ); foreach ($this->flowList as $key => $val) { $this->edgeTo[$key] = 0; $this->traversalMark[$key] = false; } } /** * 获取第一个节点 */ public function getFirstNode() { $firstNodeId = $this->_getFirstNodeId(); if (empty($firstNodeId)) { return null; } $nodeClass = Node::$nodeClasses[strtoupper($this->flowList[$firstNodeId]['nodeType'])]; return new $nodeClass($this->flowList[$firstNodeId]); } /** * */ private function _getFirstNodeId() { if (empty($this->flowList)) { return null; } foreach ($this->flowList as $domId => $node) { if (substr($domId, 0, 5) == 'start') { return $domId; } } } /*** * 获取某节点的父节点数组 * * */ function getParentNodes($nodeId) { $_nodes = array(); if (empty($this->flowList)) { return $_nodes; } foreach ($this->flowList as $domId => $node) { if (in_array($node['targetId'], $nodeId)) { array_push($_nodes, $this->getNode($node)); } } return $_nodes; } /** * 获取前一层所有节点 * @param String nodeId 节点ID * @param String nodeType 节点类型 * @return Array [TASK_NODE=>['',.....], * LOGIC_NODE=>['',.....], * SPLIT_NODE=>['',.....] * ] */ public function getPrevLevelNodes($nodeId, $nodeType = Node::ALL_NODE) { $_nodes = array(); if (empty($this->flowList) || !array_key_exists($nodeId, $this->flowList)) { return $_nodes; } foreach ($this->flowList as $domId => $node) { //如果表中节点的目标节点中包含参数节点 if (in_array($nodeId, $node['targetId'])) { //获取节点类型 $currentNodeType = array_search(ucfirst($node['nodeType']), Node::$nodeClasses); foreach (Node::$nodeTypes as $types) { //如果匹配到上层有匹配的节点 if (($currentNodeType == ($nodeType & $types))) { $_nodes[$currentNodeType][] = $this->getNode($node); } } } } return $_nodes; } /** * 获取同一层的所有节点 * @param String nodeId 节点ID * @param String nodeType 节点类型 * @return Array [TASK_NODE=>['',.....], * LOGIC_NODE=>['',.....], * SPLIT_NODE=>['',.....] * ] */ private function getSameLevelNodes($nodeId, $nodeType = Node::ALL_NODE) { $_nodes = array(); if (empty($this->flowList) || !array_key_exists($nodeId, $this->flowList)) { return _nodes; } $_parentNodes = $this->getPrevLevelNodes($nodeId, $nodeType); if (count($_parentNodes) == 0) { return $_nodes; } //如果有多个父节点,说明当前这层只有一个节点 if (count($_parentNodes) >= 2) { $currentNodeType = array_search( ucfirst($this->flowList[$nodeId]['nodeType']), Node::$nodeClasses ); foreach (Node::$nodeTypes as $types) { if (($currentNodeType == ($nodeType & $types))) { $_nodes[$currentNodeType][] = $this->getNode($this->flowList[$nodeId]); } } return $_nodes; } //如果只有一个父节点,遍历该父节点的所有节点 $pNode = $_parentNodes[0]; return $this->getNextLevelNodes($pNode->getNodeId(), $nodeType); } /** * 获取下一层的所有节点 * @param String nodeId 节点ID * @param String nodeType 节点类型 * @return Array [TASK_NODE=>['',.....], * LOGIC_NODE=>['',.....], * SPLIT_NODE=>['',.....] * ] */ public function getNextLevelNodes($nodeId, $nodeType = Node::ALL_NODE) { if (empty($this->flowList) || !array_key_exists($nodeId, $this->flowList)) { return null; } $_nodes = array(); $nextLevelIDs = $this->flowList[$nodeId]["targetId"]; foreach ($nextLevelIDs as $nextId) { $currentNodeType = array_search( strtoupper($this->flowList[$nextId]['nodeType']), Node::$nodeTypes ); // echo " nextId :" . var_dump( $currentNodeType); // var_dump(strtoupper ($this->flowList[$nextId]['nodeType'])); // var_dump($currentNodeType); $nodeType = is_array($nodeType) ? $nodeType : [$nodeType]; if ($currentNodeType && in_array(strtoupper(Node::$nodeTypes[$currentNodeType]), $nodeType)) { $_nodes[strtoupper(Node::$nodeTypes[$currentNodeType])][] = $this->getNode($this->flowList[$nextId]); } } return $_nodes; } /** * @param String code 节点flowCode * @param String nodeType 节点类型 * @return Array [TASK_NODE=>['',.....], * LOGIC_NODE=>['',.....], * SPLIT_NODE=>['',.....] * ] */ function getNextNodes($code, $nodeType = Node::ALL_NODE) { $node = $this->getNodeByCode($code); // var_dump($node); // var_dump($this->getNextLevelNodes($node->getNodeId(), $nodeType)); return $this->getNextLevelNodes($node->getNodeId(), $nodeType); } /** * 获取最后节点,如果nodeId不未 空,则获取nodeId所在流程的所有结案节点 * @param String nodeId * @return Array 结案节点的集合 */ function getFinalCodes() { $arrNode = array(); if (empty($this->flowList)) { return null; } foreach ($this->flowList as $domId => $node) { if (substr($domId, 0, 3) == 'end') { array_push($arrNode, $node['flowCode']); } } return $arrNode; } public function getNodeIdByCode($code) { $node = $this->getNodeByCode($code); if (!empty($node)) { return $node->getNodeId(); } return null; } /*** * 根据nodeId 获取Code * * @param $nodeId * @return null|*Node */ public function getNodeCodeByKey($nodeId) { if (empty($this->flowList) || !array_key_exists($nodeId, $this->flowList)) { return null; } return $this->flowList[$nodeId]['flowCode']; } private function loadGraphByJson() { } /** * 根据nodeId获取对应的节点 * @param $node * @return mixed */ public function getNode($node) { try { // var_dump($node); // var_dump($node['nodeType']); $_nodeClass = Node::$nodeClasses[strtoupper($node['nodeType'])]; // var_dump(strtoupper(Node::$nodeClasses[$node['nodeType']])); return new $_nodeClass($node); // exit(); } catch (Exception $exception) { // var_dump(strtoupper(Node::$nodeClasses[$node['nodeType']])); echo $exception->getMessage(); } } /*** *根据Key值获取节点对象 * @param $nodeId * @return mixed|null */ public function getNodeByNodeId($nodeId) { if (empty($this->flowList) || !array_key_exists($nodeId, $this->flowList)) { return null; } $_node = $this->flowList[$nodeId]; return $this->getNode($_node); } /*** *根据Code值获取节点对象 * @param $code * @return mixed|null */ public function getNodeByCode($code) { if (empty($this->flowList)) { return null; } foreach ($this->flowList as $domId => $node) { if (array_key_exists('flowCode', $node) and $node['flowCode'] == $code) { return $this->getNodeByNodeId($node['nodeId']); } } return null; } public function getAllNode($nodeType = Node::ALL_NODE) { if (empty($this->flowList)) { return null; } $_nodes = array(); foreach ($this->flowList as $domId => $node) { $currentNodeType = array_search( strtoupper($node['nodeType']), Node::$nodeClasses ); // var_dump($currentNodeType); if ($currentNodeType && !empty($currentNodeType)) { $_nodes[Node::$nodeTypes[strtoupper($currentNodeType)]][] = $this->getNode($node); } } return $_nodes; } /** * 获取流程的信息 * @return array */ public function getFlowInfo() { return $this->flowInfo; } /** * 获取两个节点之间的最短 长度 * @param null $targetId * @param null $sourceId * @return array|null */ public function getMinLengthBetweenNode($targetId = null, $sourceId = null) { if (empty($targetId)) return null; $this->sourceId = (empty($sourceId) ? $this->_getFirstNodeId() : $sourceId); $this->BreadthFirstSearchPaths(); return $this->pathTo($targetId); } /** * 使用深度优先获取路径 */ function DepthFirstSearchPaths() { //重置计数 $this->traversalMark = array(); $this->count = 0; foreach ($this->flowList as $key => $val) { $this->traversalMark[$key] = false; $this->edgeTo[$key] = 0; } $_id = empty($this->sourceId) ? $this->_getFirstNodeId() : $this->sourceId; //$edgeTo $this->dfs($_id); } /** * 使用广度优先获取路径 */ function BreadthFirstSearchPaths() { //重置计数 $this->traversalMark = array(); $this->count = 0; foreach ($this->flowList as $key => $val) { $this->traversalMark[$key] = false; $this->edgeTo[$key] = 0; } $_id = empty($this->sourceId) ? $this->_getFirstNodeId() : $this->sourceId; //$edgeTo $this->bfs($_id); } /** * 深度优先遍历 * @param $v */ private function dfs($v) { $this->count++; $this->traversalMark[$v] = true; $target = $this->flowList[$v]["targetId"]; foreach ($target as $_id) { if (empty($this->traversalMark[$_id])) { $this->edgeTo[$_id] = $v; $this->dfs($_id); } } } /** * 广度优先遍历 */ private function bfs($v) { $queue = array(); array_push($queue, $v); $this->traversalMark[$v] = true; while (count($queue) > 0) { $_id = array_shift($queue); $target = $this->flowList[$_id]["targetId"]; foreach ($target as $n_id) { if (empty($this->traversalMark[$n_id])) { $this->edgeTo[$n_id] = $_id; $this->traversalMark[$n_id] = true; array_push($queue, $n_id); } } } } /** * 判断是否有路径 * @param $v * @return mixed */ private function hasPathTo($v) { return $this->traversalMark[$v]; } function pathTo($v) { if (!$this->hasPathTo($v)) { return array(); } $stack = array(); try { for ($x = $v; $x != $this->sourceId; $x = $this->edgeTo[$x]) { array_push($stack, $x); } } catch (Exception $exception) { echo $exception->getMessage(); } // array_push($stack, $this->sourceId); return $stack; } }