diff --git a/workflow/FlowContext.php b/workflow/FlowContext.php new file mode 100644 index 00000000..473136f2 --- /dev/null +++ b/workflow/FlowContext.php @@ -0,0 +1,217 @@ +currentNode; + } + + /** + * @param mixed|null $currentNode + * @return FlowContext + */ + public function setCurrentNode($currentNode) + { + $this->currentNode = $currentNode; + return $this; + } + + /** + * @return mixed + */ + public function getSystemId() + { + return $this->systemId; + } + + /** + * @param mixed $systemId + * @return FlowContext + */ + public function setSystemId($systemId) + { + $this->systemId = $systemId; + return $this; + } + + /** + * @return mixed + */ + public function getFlowId() + { + return $this->flowId; + } + + /** + * @param mixed $flowId + * @return FlowContext + */ + public function setFlowId($flowId) + { + $this->flowId = $flowId; + return $this; + } + + /** + * @return mixed + */ + public function getFormId() + { + return $this->formId; + } + + /** + * @param mixed $formId + * @return FlowContext + */ + public function setFormId($formId) + { + $this->formId = $formId; + return $this; + } + + /** + * @return mixed + */ + public function getCurrentUser() + { + return $this->currentAssigner; + } + + /** + * @param mixed $currentAssigner + * @return FlowContext + */ + public function setCurrentUser($currentAssigner) + { + $this->currentAssigner = $currentAssigner; + return $this; + } + + /** + * @return mixed + */ + public function getFlowCode() + { + return $this->flowCode; + } + + /** + * @param mixed $flowCode + * @return FlowContext + */ + public function setFlowCode($flowCode) + { + $this->flowCode = $flowCode; + return $this; + } + + /** + * @return mixed + */ + public function getNextAssigner() + { + return $this->nextAssigner; + } + + /** + * @param mixed $nextAssigner + * @return FlowContext + */ + public function setNextAssigner($nextAssigner) + { + $this->nextAssigner = $nextAssigner; + return $this; + } + + /** + * @return mixed + */ + public function getAssignStatus() + { + return $this->assignStatus; + } + + /** + * @param mixed $assignStatus + * @return FlowContext + */ + public function setAssignStatus($assignStatus) + { + $this->assignStatus = $assignStatus; + return $this; + } + + /** + * @return mixed + */ + public function getAssignOpinion() + { + return $this->assignOpinion; + } + + /** + * @param mixed $assignOpinion + * @return FlowContext + */ + public function setAssignOpinion($assignOpinion) + { + $this->assignOpinion = $assignOpinion; + return $this; + } + + /** + * @return mixed + */ + public function getFormKey() + { + return $this->formKey; + } + + /** + * @param mixed $formKey + * @return FlowContext + */ + public function setFormKey($formKey) + { + $this->formKey = $formKey; + return $this; + } + + /** + * @return mixed + */ + public function getWorkFLowParser() + { + return $this->workFlowParser; + } + + /** + * @param mixed $workFlowParser + * @return FlowContext + */ + public function setWorkFLowParser($workFlowParser) + { + $this->workFlowParser = $workFlowParser; + return $this; + } +} diff --git a/workflow/Handler/B4TaskHandler.php b/workflow/Handler/B4TaskHandler.php new file mode 100644 index 00000000..99419ce6 --- /dev/null +++ b/workflow/Handler/B4TaskHandler.php @@ -0,0 +1,38 @@ +parseRole(); + foreach ($nextAssigners as $row) { + + foreach ($assigners as $key => $assigner) { + + if ($assigners[$key][0] == $row['assign_status']) { + $assigners[$key][1] = $row['assigner_string']; + } else { + array_push($assigners, array(0 => $row['assign_status'], 1 => $row['assigner_string'])); + } + } + + } + return $assigners; + } + +} \ No newline at end of file diff --git a/workflow/Handler/B7TaskHandler.php b/workflow/Handler/B7TaskHandler.php new file mode 100644 index 00000000..76b24fae --- /dev/null +++ b/workflow/Handler/B7TaskHandler.php @@ -0,0 +1,38 @@ +parseRole(); + foreach ($nextAssigners as $row) { + + foreach ($assigners as $key => $assigner) { + + if ($assigners[$key][0] == $row['assign_status']) { + $assigners[$key][1] = $row['assigner_string']; + } else { + array_push($assigners, array(0 => $row['assign_status'], 1 => $row['assigner_string'])); + } + } + + } + return $assigners; + } + +} \ No newline at end of file diff --git a/workflow/Handler/CounterSignSubtaskHandler.php b/workflow/Handler/CounterSignSubtaskHandler.php new file mode 100644 index 00000000..c575dc38 --- /dev/null +++ b/workflow/Handler/CounterSignSubtaskHandler.php @@ -0,0 +1,141 @@ +formData = $formData; + $this->flowContext = $flowContext; + $parser = $flowContext->getWorkFLowParser(); + + $this->currentNode = $parser->getNodeByCode($flowContext->getFlowCode()); + + } + + /** + * 1,根据签核状态变更workflow_sublow reply_flag Y:同意; N:不同意; NULL:未回复 + */ + public function doWork() + { + $flow = new Flow ($this->flowContext->getFormKey()); + $sm = new SubflowManager(new Flow($flow->getParentKey())); + #是否同意标志 + $flag = $this->flowContext->getAssignStatus() == AssignStatus::ACCEPT_STATUS ? 'Y' : 'N'; + SubflowManager::updateReplyFlag($this->flowContext->getFormKey(), $flag); + SubflowManager::updateReplyComment($this->flowContext->getFormKey(), $this->flowContext->getAssignOpinion()); + + $unReplyCount = $sm->getUnReplyCount(SubflowManager::getSeqByFormKey($this->flowContext->formKey)); + if ($unReplyCount == 0) { + $mergeOption = $this->currentNode->getMergeOption(); + $mergeOption = empty($mergeOption) ? self::DEFAULT_MERGE_OPTION : $mergeOption; + $function = "cond" . strtoupper($mergeOption); + $this->$function($sm); + } + #关闭任务 + $task = new NodeTask(); + $task->setFormKey($this->flowContext->getFormKey()) + ->setFlowCode($this->flowContext->getCurrentNode()->getFlowCode()) + ->setState("OPEN") + ->setTaskType("COUNTER_SIGN_SUBTASK") + ->setPhase("SUBMIT"); + + $tasks = TaskManager::getTasks($task); + foreach ($tasks as $task) { + $task->setState(NodeTask::TASK_FINISH_STATE)->update(); + + } + + + } + + /** + * 同意一个即可 + */ + private function condOR($sm) + { + $cnt = $sm->getAcceptOpinionCount(SubflowManager::getSeqByFormKey($this->flowContext->formKey)); + if ($cnt >= 1) { + $this->nextAssign(); + } else { + $this->backAssign(); + } + } + + /** + * 全部同意 + */ + private function condAND($sm) + { + $cnt = $sm->getRejectOpinionCount(SubflowManager::getSeqByFormKey($this->flowContext->formKey)); + if ($cnt == 0) { + $this->nextAssign(); + } else { + $this->backAssign(); + } + } + + /** + *同意的占多数 + */ + private function condVOTE($sm) + { + $reject = $sm->getRejectOpinionCount(SubflowManager::getSeqByFormKey($this->flowContext->formKey)); + $accept = $sm->getAcceptOpinionCount(SubflowManager::getSeqByFormKey($this->flowContext->formKey)); + if ($accept >= $reject) { + $this->nextAssign(); + } else { + $this->backAssign(); + } + } + + private function backAssign() + { + + $currentFlow = new Flow($this->flowContext->getFormKey()); + $parentKey = $currentFlow->getParentKey(); + $prevNodes = $this->flowContext->getWorkFLowParser()->getPrevLevelNodes($this->flowContext->getCurrentNode()->getNodeId(), + Node::FLOW_NODE | Node::LOGIC_NODE); + + foreach ($prevNodes as $key => $prevNode) { + $tmpNode = $prevNode[0]; + $backFlowCode = $tmpNode->getFlowCode(); + $backAssign = Assign::get_lastest_record($parentKey, $backFlowCode); + if (empty($backFlowCode)) continue; + Flow::updateFlowCode($parentKey, $backAssign['flow_code']); + Subflow::updateCurrentUser($parentKey, $backAssign['assigner']); + } + + + } + + private function nextAssign() + { + $nextFlowNodes = $this->flowContext->getWorkFLowParser()->getNextLevelNodes($this->currentNode->getNodeId()); + $nextFlowCode = ""; + foreach (Node::$nodeTypes as $type) { + if (!array_key_exists($type, $nextFlowNodes)) continue; + foreach ($nextFlowNodes[$type] as $node) { + $nextFlowCode = $node->getFlowCode(); + $nextAssigners = $node->getAssignerList($this->flowContext->getWorkFLowParser()); + break 2; + } + } + //array(1) { [0]=> array(2) { [0]=> string(2) "F1" [1]=> string(29) "00017-贺正时 协理特助," } } + $nextAssigner = substr($nextAssigners[0][1], 0, 5); + $currentFlow = new Flow($this->flowContext->getFormKey()); + Flow::updateFlowCode($currentFlow->getParentKey(), $nextFlowCode); + Subflow::updateCurrentUser($currentFlow->getParentKey(), $nextAssigner); + + } +} \ No newline at end of file diff --git a/workflow/Handler/CounterSignTaskHandler.php b/workflow/Handler/CounterSignTaskHandler.php new file mode 100644 index 00000000..94ebcf7c --- /dev/null +++ b/workflow/Handler/CounterSignTaskHandler.php @@ -0,0 +1,115 @@ +currentNode = $node; + $this->flowContext = $Context; + $this->formData = $formData; + } + + + /** + * 1.从流程图中解析出下个节点的Code 更新 + */ + function doWork() + { + //1.获取表单数据中的split_members 为字符串 成员1,成员2, + $currentNode = $this->flowContext->getCurrentNode(); + $assignClass = $currentNode->getAssignClass(); + + $currentAssigner = $this->flowContext->getCurrentUser(); + $currentFormKey = $this->flowContext->getFormKey(); + $this->flowContext->getCurrentNode() + ->setFlow($this->flowContext); + $this->flowContext->getCurrentNode() + ->setformData($this->formData); + + if (!$currentNode->checkTrust($assignClass, Employee::lead_code($currentAssigner))) { + $handler = new FlowNodeHandler($this->currentNode, $this->flowContext, $this->formData); + $handler->doWork(); + /// Subflow::updateCurrentUser($currentFormKey, $this->flowContext->nextAssigner); + + return; + } + $splitMembers = explode(',', $this->formData['split_members']); + //2.遍历$splitMembers数组 ,对其调用,AssignerStringParser::process(),获取具体的签核人员 + $nextAssigners = array(); + $sm = new SubflowManager(new Flow($currentFormKey)); + var_dump($splitMembers); + + foreach ($splitMembers as $member) { + var_dump($member); + $nextAssigners = explode( + ',', + AssignerStringParser::process($member, $format = "employee_no", ",") + ); + #生成待签 + $seq = 0; + foreach ($nextAssigners as $assigner) { + if (empty($assigner)) continue; + $flowCode = $this->currentNode->getFLowCode(); + $childFlow = new Flow(); + $childFlow->setSystemId($this->flowContext->getSystemId()) + ->setFormId($this->flowContext->getFormId()) + ->setFlowId($this->flowContext->getFlowId()) + ->setFlowCode($flowCode) + ->insert(); + $subflow = new Subflow($childFlow); + $subflow->setCurrentUser($assigner)->insert(); + $sm->append($subflow, $currentAssigner); + #生成任务1 + $task = new NodeTask(); + $task->setFormKey($childFlow->getFormKey()) + ->setFlowCode($flowCode) + ->setState("OPEN") + ->setTaskType("COUNTER_SIGN_SUBTASK") + ->setNecessary('Y') + ->setPhase("SUBMIT") + ->setCreator($currentAssigner); + TaskManager::insertTask($task); + #生成任务1结束 + + #生成任务2 + $task = new NodeTask(); + $task->setFormKey($childFlow->getFormKey()) + ->setFlowCode($flowCode) + ->setState("OPEN") + ->setTaskType("NEXT_ASSIGNER_MODIFY_TASK") + ->setNecessary('Y') + ->setWfCondition("NEXT") + ->setJoinRole("select code_name assign_status, + case code_name when 'F1' then '00000-回传申请单位' + when 'Y1' then '00000-回传申请单位' end assigner_string from code + where code_name in('Y1','F1') and field_name='assign_status'") + ->setRoleType("SQL") + ->setPhase("LOAD") + ->setCreator($currentAssigner); + TaskManager::insertTask($task); + #生成任务2结束 $_SERVER['HTTP_HOST'] + + + } + } + + $nextAssigner = $this->flowContext->nextAssigner; + #变更流程下位签核者 + Subflow::updateCurrentUser($currentFormKey, $nextAssigner); + #挂起该流程 + Subflow::suspend($currentFormKey); + } + + private function processAssignStatusFH() + { + } + + private function processAssignStatusX3() + { + } +} diff --git a/workflow/Handler/EndNodeHandler.php b/workflow/Handler/EndNodeHandler.php new file mode 100644 index 00000000..7d1d3943 --- /dev/null +++ b/workflow/Handler/EndNodeHandler.php @@ -0,0 +1,37 @@ +currentNode=$node; + $this->flowContext=$Context; + $this->formData=$formData; + } + /** + * 根据传入FlowNode节点的中的Code 更新Flow表 + */ + function doWork(){ + + //作为一般流程节点处理 + $handler=new FlowNodeHandler( $this->currentNode,$this->flowContext,$this->formData); + $handler->doWork(); + + #删除流程上的所有任务 + $task = new NodeTask(); + $task->setFormKey($this->flowContext->getFormKey()); + $tasks = TaskManager::getTasks($task); + foreach ($tasks as $task) { + $taskCreator = $task->getCreator(); + if ($taskCreator == $this->flowContext->getNextAssigner()) { + $task->delete(); + } + } + // Flow::updateFlowCode( $this->flowContext->formKey,$this->currentNode->getFlowCode()); + + // Subflow::updateCurrentUser($this->flowContext->formKey,$this->flowContext->nextAssigner); + + } + +} \ No newline at end of file diff --git a/workflow/Handler/FhTaskHandler.php b/workflow/Handler/FhTaskHandler.php new file mode 100644 index 00000000..bb82d8b1 --- /dev/null +++ b/workflow/Handler/FhTaskHandler.php @@ -0,0 +1,31 @@ +parseRole(); + $newNextAssigners = array(); + foreach ($nextAssigners as $row) { + array_push($newNextAssigners, array(0 => $row['assign_status'], 1 => $row['assigner_string'])); + } + + return $newNextAssigners; + } +} \ No newline at end of file diff --git a/workflow/Handler/FlowNodeHandler.php b/workflow/Handler/FlowNodeHandler.php new file mode 100644 index 00000000..f5ec3c91 --- /dev/null +++ b/workflow/Handler/FlowNodeHandler.php @@ -0,0 +1,227 @@ +currentNode = $node; + $this->flowContext = $flowContext; + $this->formData = $formData; + } + + /** + * 根据传入FlowNode节点的中的Code 更新Flow表 + */ + function doWork() + { + $this->flowContext->getCurrentNode()->setFlow($this->flowContext); + $this->flowContext->getCurrentNode()->setformData($this->formData); + $function = "processAssignStatus" . $this->flowContext->getAssignStatus(); + // echo $function ; + if (!method_exists('FlowNodeHandler', $function)) { + echo self::processUndefined($function); + exit(); + } + #调用对应的处理函数 + $this->$function(); + } + + /** + * + *处理AssignStatus=F1 同意 流程进入下个节点 + * + */ + private function processAssignStatusF1() + { + $assignClass = $this->flowContext->getCurrentNode()->getAssignClass(); + + $currentAssigner = Subflow::getCurrentUser($this->flowContext->getFormKey()); + $nextFlowCode = $this->currentNode->getFlowCode(); + $formKey = $this->flowContext->getFormKey(); + $currentFlowCode = $this->flowContext->getFlowCode(); + + #符合条件,变更流程码,否则停在当前环节 + if ($this->flowContext->getCurrentNode()->checkTrust($assignClass, Employee::lead_code($currentAssigner))) { + #节点附加的任务 + $task = new NodeTask(); + $task->setFormKey($this->flowContext->formKey) + ->setFlowCode($currentFlowCode) + ->setState("OPEN") + ->setPhase("SUBMIT"); + $tasks = TaskManager::getTasks($task); + + if (count($tasks) > 0) { + foreach ($tasks as $task) { + $handlerClass = NodeTask::$handlerClasses[constant("NodeTask::" . $task->getTaskType())]; + $handler = new $handlerClass($this->flowContext, $this->formData); + $handler->doWork(); + } + } + Flow::updateFlowCode($formKey, $nextFlowCode); + #关闭当前节点上的所有任务 + $task = new NodeTask(); + $task->setFormKey($this->flowContext->getFormKey()) + ->setFlowCode($currentFlowCode) + ->setState("OPEN"); + $closeTasks = TaskManager::getTasks($task); + foreach ($closeTasks as $task) { + $task->delete(); + } + } + Subflow::updateCurrentUser($formKey, $this->flowContext->getNextAssigner()); + } + + /** + * 申请人申请S + */ + private function processAssignStatusS() + { + $this->processAssignStatusF1(); + } + + /*** + * 转工程科处理 + */ + private function processAssignStatusGC() + { + $this->processAssignStatusF1(); + } + + /*** + * 会签不同意 + */ + private function processAssignStatusY1() + { + $this->processAssignStatusF1(); + } + + /** + *处理AssignStatus=FH 指派 流程还停留在当前节点 + * 在LOAD阶段需要添加一个任务,使得被指派人选择下位签核者时,既能呈核,也能指派 + * + */ + private function processAssignStatusFH() + { + #生成任务 + // echo "processAssignStatusFH"; + $currentAssigner = new Employee(Subflow::getCurrentUser($this->flowContext->getFormKey())); + $nextUser = new Employee($this->flowContext->getNextAssigner()); + // var_dump( $this->flowContext->getFormKey()); + $task = new NodeTask(); + $task->setFormKey($this->flowContext->getFormKey()) + ->setFlowCode($this->flowContext->getFlowCode()) + ->setState("OPEN") + ->setTaskType("FH_TASK") + ->setNecessary('Y') + ->setPhase("LOAD") + ->setWfCondition("SAME") + ->setJoinRole("select 'F6' assign_status, concat( + '" . $currentAssigner->employee_no . "' , '-','" . $currentAssigner->name . "' ) assigner_string from dual + union select 'FH' assign_status,concat(employee_no,'-',name) assigner_string from employee where + depart_no like '" . rtrim($nextUser->depart_no, 0) . "%' + and employee_no!='" . $nextUser->employee_no . "' + and lead_code >'" . $nextUser->lead_code . "'") + ->setRoleType('SQL') + ->setCreator($currentAssigner->employee_no) + ->setCreateCode($this->flowContext->getFlowCode()); + TaskManager::insertTask($task); + + + Subflow::updateCurrentUser($this->flowContext->getFormKey(), $this->flowContext->getNextAssigner()); + } + + /** + * 处理AssignStatus=F6 呈核 流程还停留在当前节点,如果下位签核者,是 + */ + private function processAssignStatusF6() + { + #生成任务 + $task = new NodeTask(); + $task->setFormKey($this->flowContext->getFormKey()) + ->setFlowCode($this->flowContext->getCurrentNode()->getFlowCode()) + ->setState("OPEN") + ->setTaskType("FH_TASK") + ->setPhase("LOAD"); + $tasks = TaskManager::getTasks($task); + // var_dump($task); + foreach ($tasks as $task) { + $taskCreator = $task->getCreator(); + // var_dump($this->flowContext->getNextAssigner() ); + // var_dump($taskCreator); + if ($taskCreator == $this->flowContext->getNextAssigner()) { + $task->setState(NodeTask::TASK_FINISH_STATE)->update(); + } + } + Subflow::updateCurrentUser($this->flowContext->getFormKey(), $this->flowContext->getNextAssigner()); + } + + /** + * 处理AssignStatus=B4 退回上一个节点 + */ + private function processAssignStatusB4() + { + + $formKey = $this->flowContext->getFormKey(); + $prevNodes = $this->flowContext->workFlowParser->getPrevLevelNodes( + $this->flowContext->getCurrentNode()->getNodeId(), + [Node::FLOW_NODE, Node::LOGIC_NODE] + ); + + foreach ($prevNodes as $key => $prevNode) { + $tmpNode = $prevNode[0]; + $backFlowCode = $tmpNode->getFlowCode(); + + $backAssign = Assign::get_lastest_record($formKey, $backFlowCode); + if (empty($backFlowCode)) continue; + Flow::updateFlowCode($formKey, $backAssign['flow_code']); + } + Subflow::updateCurrentUser($formKey, $this->flowContext->getNextAssigner()); + } + + /** + * 处理AssignStatus=B7 退回申请人 + */ + private function processAssignStatusB7() + { + + $formKey = $this->flowContext->getFormKey(); + + + #删除当前节点上的所有任务 + $task = new NodeTask(); + $task->setFormKey($formKey) + ->setFlowCode($this->flowContext->getCurrentNode()->getFlowCode()) + ->setState("OPEN"); + + $closeTasks = TaskManager::getTasks($task); + foreach ($closeTasks as $task) { + $task->setState(NodeTask::TASK_FINISH_STATE)->update(); + } + + $startNode = $this->flowContext->getWorkFLowParser()->getFirstNode(); + + Flow::updateFlowCode($formKey, $startNode->getFlowCode()); + Subflow::updateCurrentUser($formKey, $this->flowContext->getNextAssigner()); + } + + private function processAssignStatusF4() + { + $formKey = $this->flowContext->getFormKey(); + Flow::updateFlowCode($formKey, $this->currentNode->getFlowCode()); + Subflow::updateCurrentUser($formKey, $this->flowContext->getNextAssigner()); + } + + /** + * 处理异常 + * @param $function + * @return string + */ + private function processUndefined($function) + { + return "调用的不存在方法" . $function; + } +} diff --git a/workflow/Handler/LogicNodeHandler.php b/workflow/Handler/LogicNodeHandler.php new file mode 100644 index 00000000..b1ceaddb --- /dev/null +++ b/workflow/Handler/LogicNodeHandler.php @@ -0,0 +1,76 @@ +currentNode = $node; + $this->flowContext = $Context; + $this->formData = $formData; + } + + /** + * 判断传入的assignStatus,在下层节点中找出含有该assignStatus的节点 + */ + function doWork() + { + + #停留在当前节点 + if ( + in_array($this->flowContext->assignStatus, AssignStatus::$same_level_status) + or in_array($this->flowContext->assignStatus, AssignStatus::$back_status) + ) { + $flowHandler = new FlowNodeHandler($this->currentNode, $this->flowContext, $this->formData); + $flowHandler->doWork(); + return; + } + $formKey = $this->flowContext->getFormKey(); + #检查是否有下节点是否定routeMethod + $routeMethod = $this->currentNode->getRouteMethod(); + $nextFlowCode = ""; + $assignClass = $this->flowContext->getCurrentNode()->getAssignClass(); + if (!empty($routeMethod)) { + $nextFlowCode = $routeMethod->invokeMethod($this->flowContext, $this->formData); + } else { + #根据下层节点的assign_status 匹配 + + $workFlowParser = $this->flowContext->getWorkFLowParser(); + //解析下层节点\WorkFlowParser::getNextLevelNodes + $nextFlowNodes = $workFlowParser->getNextLevelNodes($this->currentNode->getNodeId()); + foreach (Node::$nodeTypes as $type) { + if (!array_key_exists($type, $nextFlowNodes)) continue; + foreach ($nextFlowNodes[$type] as $node) { + if (method_exists($node, 'getAssignerList')) { + $assigner = $node->getAssignerList($workFlowParser); + $assign_status = $assigner[0][0]; + if ($assign_status == $this->flowContext->getAssignStatus()) { + $nextFlowCode = $node->getFlowCode(); + break 2; + } + } + } + } + } + + + #当前签核者 + $currentAssignerId = $this->flowContext->getCurrentUser(); + + if ($this->flowContext->currentNode->checkTrust($assignClass, Employee::lead_code($currentAssignerId))) { + Flow::updateFlowCode($formKey, $nextFlowCode); + } + + Subflow::updateCurrentUser($formKey, $this->flowContext->getNextAssigner()); + } +} diff --git a/workflow/Handler/MergeNodeHandler.php b/workflow/Handler/MergeNodeHandler.php new file mode 100644 index 00000000..15f67361 --- /dev/null +++ b/workflow/Handler/MergeNodeHandler.php @@ -0,0 +1,108 @@ +currentNode = $node; + $this->flowContext = $Context; + } + + /** + * 1.从流程图中解析出下个节点的Code 更新 + */ + function doWork() + { + + $flow = new Flow($this->flowContext->getFormKey()); + + $sm = new SubflowManager(new Flow($flow->getParentKey())); + $flag = $this->flowContext->assignStatus == AssignStatus::ACCEPT_STATUS ? 'Y' : 'N'; + SubflowManager::updateReplyFlag($flow->getFormKey(), $flag); + + $unReplyCount = $sm->getUnReplyCount(SubflowManager::getSeqByFormKey($flow->getFormKey())); + if ($unReplyCount == 0) { + $mergeOption = $this->currentNode->getMergeOption(); + $mergeOption = empty($mergeOption) ? self::DEFAULT_MERGE_OPTION : $mergeOption; + $function = "cond" . strtoupper($mergeOption); + $this->$function($sm); + Subflow::delete($flow->getFormKey()); + } + + /** + *遍历所有下层节点 ,执行对应Handler类doWork方法 + */ + } + + /** + * 同意一个即可 + * @param SubflowManager $sm + */ + private function condOR(SubflowManager $sm) + { + $cnt = $sm->getAcceptOpinionCount(SubflowManager::getSeqByFormKey($this->flowContext->formKey)); + if ($cnt >= 1) { + $this->nextAssign(); + } else { + $this->backAssign(); + } + } + + /** + * 全部同意 + * @param SubflowManager $sm + */ + private function condAND(SubflowManager $sm) + { + $cnt = $sm->getRejectOpinionCount(SubflowManager::getSeqByFormKey($this->flowContext->formKey)); + if ($cnt == 0) { + $this->nextAssign(); + } else { + $this->backAssign(); + } + } + + /** + *同意的占多数 + * @param SubflowManager $sm + */ + private function condVOTE(SubflowManager $sm) + { + $reject = $sm->getRejectOpinionCount(SubflowManager::getSeqByFormKey($this->flowContext->formKey)); + $accept = $sm->getAcceptOpinionCount(SubflowManager::getSeqByFormKey($this->flowContext->formKey)); + if ($accept >= $reject) { + $this->nextAssign(); + } else { + $this->backAssign(); + } + } + + private function backAssign() + { + $code = SubflowManager::getCurrentParentFlowCode($this->flowContext->formKey); + $node = $this->flowContext->workFlowParser->getNodeByCode($code); + $handleClass = get_class($node) . "Handler"; + $obj = new $handleClass($node, $this->flowContext, $this->formData); + $obj->doWork(); + } + + private function nextAssign() + { + $nextAssigner = $this->flowContext->nextAssigner; + $nextFlowNodes = $this->flowContext->workFlowParser->getNextLevelNodes($this->currentNode->getNodeId()); + foreach (Node::$nodeTypes as $type) { + if (!array_key_exists($type, $nextFlowNodes)) continue; + foreach ($nextFlowNodes[$type] as $node) { + $nextFlowCode = $node->getFlowCode(); + break 2; + } + } + $currentFlow = new Flow($this->flowContext->formKey); + Flow::updateFlowCode($currentFlow->getParentKey(), $nextFlowCode); + // Subflow::updateCurrentUser($currentFlow->getParentKey(), $nextAssigner); + } +} diff --git a/workflow/Handler/NextAssignerModifyTaskHandler.php b/workflow/Handler/NextAssignerModifyTaskHandler.php new file mode 100644 index 00000000..fc8a0eea --- /dev/null +++ b/workflow/Handler/NextAssignerModifyTaskHandler.php @@ -0,0 +1,52 @@ +parseRole(); + $newNextAssigners = array(); + foreach ($nextAssigners as $row) { + array_push($newNextAssigners, array(0 => $row['assign_status'], 1 => $row['assigner_string'])); + } + + return $newNextAssigners; + + } + /* public function setNextAssignerList(array $assigners, NodeTask $task) + { + $nextAssigners = $task->parseRole(); + foreach ($nextAssigners as $row) { + + foreach ($assigners as $key => $assigner) { + + if ($assigners[$key][0] == $row['assign_status']) { + $assigners[$key][1] = $row['assigner_string']; + } else { + array_push($assigners, array(0 => $row['assign_status'], 1 => $row['assigner_string'])); + } + + } + + } + + return $assigners; + }*/ +} \ No newline at end of file diff --git a/workflow/Handler/SplitNodeHandler.php b/workflow/Handler/SplitNodeHandler.php new file mode 100644 index 00000000..ec7d619e --- /dev/null +++ b/workflow/Handler/SplitNodeHandler.php @@ -0,0 +1,58 @@ +currentNode = $node; + $this->flowContext = $flowContext; + } + + /** + * 1.从流程图中解析出下个节点的Code 更新 + *$assigners 数组结构: array(1) { [0]=> array(2) { [0]=> string(2) "F1" [1]=> string(15) "73502-包 博," } } + */ + function doWork() + { + + //解析下层节点\WorkFlowParser::getNextLevelNodes + $nextFlowNodes = $this->flowContext->getWorkFLowParser() + ->getNextLevelNodes($this->currentNode->getNodeId()); + $sm = new SubflowManager(new Flow($this->flowContext->getFormKey())); + foreach (Node::$nodeTypes as $type) { + if (!array_key_exists($type, $nextFlowNodes)) continue; + $seq = 0; + foreach ($nextFlowNodes[$type] as $node) { + if (method_exists($node, 'getAssignerList')) { + $assigners = $node->getAssignerList($this->flowContext->getWorkFLowParser()); + $tmp = (array)(explode('-', $assigners[0][1])); + $emp = $tmp[0]; + $nextFlowCode = $node->getFlowCode(); + $childFlow = new Flow(); + $childFlow->setSystemId($this->flowContext->systemId) + ->setFlowId($this->flowContext->flowId) + ->setFormId($this->flowContext->formId) + ->setFlowCode($nextFlowCode) + ->insert(); + $subflow = new Subflow($childFlow); + $subflow->setCurrentUser($emp)->insert(); + $sm->append($subflow, $this->flowContext->getCurrentUser()); + + echo "会签 " . $seq++ . ":查看下笔链接" . "
"; + } + } + } + $nextAssigner = $this->flowContext->getNextAssigner(); + $currentFlow = new Flow($this->flowContext->getFormKey()); + Subflow::updateCurrentUser($currentFlow->getParentKey(), $nextAssigner); + //exit(); + + /** + *遍历所有下层节点 ,执行对应Handler类doWork方法 + */ + } +} diff --git a/workflow/Handler/StartNodeHandler.php b/workflow/Handler/StartNodeHandler.php new file mode 100644 index 00000000..d7efb6f7 --- /dev/null +++ b/workflow/Handler/StartNodeHandler.php @@ -0,0 +1,28 @@ +currentNode = $node; + $this->flowContext = $Context; + } + + /** + * 根据传入FlowNode节点的中的Code 更新Flow表 + */ + function doWork() + { + # echo " StartNodeHandler 31:".$this->flowContext->getFormKey(); + $flow = new Flow ($this->flowContext->getFormKey()); + $flow->setFlowCode($this->currentNode->getFlowCode())->save(); + $subflow = new Subflow($flow); + $subflow->setCurrentUser($this->flowContext->getNextAssigner())->insert(); + + } + +} \ No newline at end of file diff --git a/workflow/WorkFlow.php b/workflow/WorkFlow.php new file mode 100644 index 00000000..7ef6f0bd --- /dev/null +++ b/workflow/WorkFlow.php @@ -0,0 +1,445 @@ +log = new Logger(dirname(__FILE__) . "/" + . (self::$logPath), Logger::DEBUG); + + $this->systemId = $systemId; + $this->flowId = $flowId; + $this->formId = $formId; + + $this->currentFlow = new Flow($formKey); + + $_parentKey = $this->currentFlow->getParentKey(); + //当流程不是处 于会签和子流程状态时 $mainFlow 和 $currentFlow是一个对象 + $this->mainFlow = ($_parentKey == null or empty($_parentKey)) + ? $this->currentFlow : new Flow($_parentKey); + $this->workFlowParser = new WorkFlowParser($systemId, $flowId); + $this->flowContext = new FlowContext(); + # var_dump( $this->flowContext); + // echo " WorkFLow 31:".$this->currentFlow->getFormKey(); + + $this->flowContext->setFormKey($this->currentFlow->getFormKey()) + ->setSystemId($this->systemId) + ->setFlowId($this->flowId) + ->setFormId($this->formId) + ->setWorkFLowParser($this->workFlowParser); + + $_SESSION['flowContext'] = serialize($this->flowContext); + // var_dump($this); + } + + /** + * + * @param $userId 流程初始化人员 + */ + public function initWorkFlow($userId) + { //var_dump($this->formId); + + // var_dump($this); + $this->currentFlow->setSystemId($this->systemId) + ->setFlowId($this->flowId) + ->setFormId($this->formId) + ->setFlowCode($this->getFirstFlowCode()) + ->save(); + // var_dump($userId); + $this->flowContext->setNextAssigner($userId) + ->setAssignStatus('S'); + + $start = new StartNodeHandler($this->workFlowParser->getFirstNode(), $this->flowContext, $this->formData); + // var_dump( $this->flowContext); + #执行开始节点预置的操作 + $start->doWork(); + #写入日志 + // $this->log->logInfo("$userId 启动了流程 system:'" . $this->systemId . ";flow:" . $this->formId); + } + + /** + * 设置多个签核接受人员 + * @param array $members + */ + function setSplitMembers($members = array()) + { + } + + /** + *1.先检查是否满足签核下 + */ + public function submit() + { + #获取FlowContext的值 + $nextAssigner = $this->flowContext->getNextAssigner(); + $assignStatus = $this->flowContext->getAssignStatus(); + $assignOpinion = $this->flowContext->getAssignOpinion(); + #获取所有下层Node数组 + $nodes = $this->workFlowParser + ->getNextNodes($this->currentFlow->getFlowCode()); + #设置当前节点数据 + $this->flowContext->setCurrentNode($this->workFlowParser + ->getNodeByCode($this->currentFlow->getFlowCode())); + #设置要传入 Handler实例的Context 实例 + + $this->flowContext->getCurrentNode()->setFlow($this->flowContext) + ->setformData($this->formData); + // $this->flowContext->getCurrentNode()->setformData($this->formData); + + $asg = new Assign($this->currentFlow->getFormKey()); + if ( + $this->flowContext->getCurrentNode()->getType() == 'start_node' + and $asg->getSeq() == '0' + ) { + $this->flowContext->setAssignStatus('S'); + } + //var_dump(Subflow::getCurrentUser($this->currentFlow->getFormKey())); + $asg->setAssigner(Subflow::getCurrentUser($this->currentFlow->getFormKey())) + ->setAssignStatus($this->flowContext->getAssignStatus()) + ->setAssignOpinion($assignOpinion) + ->setFlowCode($this->currentFlow->getFlowCode()) + ->setFlowCodeSeq(0)->insert(); + + #记录日志 + $_log_array = array( + "nextAssigner" => $nextAssigner, + "assignStatus" => $assignStatus, + "nextAssigner" => $nextAssigner, + "currentAssigner" => Subflow::getCurrentUser($this->currentFlow->getFormKey()), + "flow_code" => $this->currentFlow->getFlowCode() + ); + $this->log->logInfo("" . ID . " 提交了流程 system:'" . $this->systemId . ";flow:" . $this->flowId, $_log_array); + + #插入assign表信息 + + $_SESSION['flowContext'] = serialize($this->flowContext); + // var_dump($nodes); + foreach (Node::$nodeTypes as $type) { + if (!array_key_exists($type, $nodes)) continue; + foreach ($nodes[$type] as $node) { + $handleClass = get_class($node) . "Handler"; + $obj = new $handleClass($node, $this->flowContext, $this->formData); + $obj->doWork(); + } + } + } + + /* + *获取签核人员列表 + */ + public function getAssignerList() + { + $currentNode = $this->workFlowParser + ->getNodeByCode($this->currentFlow->getFlowCode()); + #获取当前签核者 + $currentFormKey = $this->currentFlow->getFormKey(); + $currentAssigner = Subflow::getCurrentUser($currentFormKey); + #读取签核类别 A是专人的签核 + + #遍历下层节点读取下层节点的签核人员 + $currentNode->setFlow($this->flowContext) + ->setFormData($this->formData); + $assignClass = $currentNode->getAssignClass(); + + if ($currentNode->checkTrust($assignClass, Employee::lead_code($currentAssigner))) { + + #获取所有下层Node数组,并遍历,调用其中getAssignerList 方法 + $nodes = $this->workFlowParser->getNextNodes($this->currentFlow->getFlowCode()); + // var_dump($nodes); + + $assigner = array(); + foreach (Node::$nodeTypes as $type) { + if (!array_key_exists($type, $nodes)) continue; + foreach ($nodes[$type] as $node) { + if (method_exists($node, 'getAssignerList')) { + $assigner = array_merge( + (array)$assigner, + $node->getAssignerList($this->workFlowParser) + ); + } + } + } + + #检查退回选项 + $backOption = $currentNode->getBackOption(); + //B4 退回上一个节点 + if ($backOption == 'B4') { + $prevNodes = $this->flowContext->workFlowParser->getPrevLevelNodes( + $currentNode->getNodeId(), + [Node::FLOW_NODE, Node::LOGIC_NODE] + ); + foreach ($prevNodes as $key => $prevNode) { + $tmpNode = $prevNode[0]; + $backAssign = Assign::get_lastest_record($currentFormKey, $tmpNode->getFlowCode()); + $backUser = $backAssign['assigner']; + if (empty($backUser)) continue; + $nextAssignerStr = ""; + $nextAssignerStr .= Employee::get_employee($backUser, $format = "employee_no-name") . ','; + array_push($assigner, array(0 => 'B4', 1 => $nextAssignerStr)); + } + } + #B7 退回申请人 + if ($backOption == 'B7') { + $assign = Assign::get_records($currentFormKey, true, '%', 'S'); + // var_dump($assign); + $applicant = $assign[0]['assigner']; + $nextAssignerStr = ""; + $nextAssignerStr .= Employee::get_employee($applicant, $format = "employee_no-name") . ','; + array_push($assigner, array(0 => 'B7', 1 => $nextAssignerStr)); + } + + #获取任务节点,查看是否有修改签核者的的任务 + $task = new NodeTask(); + $task->setFormKey($this->currentFlow->getFormKey()) + ->setFlowCode($this->currentFlow->getFlowCode()) + ->setState("OPEN") + ->setPhase("LOAD"); + $tasks = TaskManager::getTasks($task); + if (count($tasks) > 0) { + foreach ($tasks as $task) { + $handlerClass = NodeTask::$handlerClasses[constant("NodeTask::" . $task->getTaskType())]; + $handler = new $handlerClass($this->flowContext, $this->formData); + if (method_exists($handler, 'setNextAssignerList')) { + + $assigner = $handler->setNextAssignerList($assigner, $task); + } + } + } + + #也可以指派给自己的下属 + $subordinates = Employee::subordinates($currentAssigner); + if (count($subordinates) > 0) { + $nextAssignerStr = ""; + foreach ($subordinates as $emp) { + $nextAssignerStr .= Employee::get_employee($emp, $format = "employee_no-name") . ','; + } + array_push($assigner, array(0 => 'FH', 1 => $nextAssignerStr)); + } + + $nextAssigner = $assigner; + } else { + #需要签给上级领导审 + $nextAssigner = $currentNode->getDepartmentalAssignerList($currentAssigner); + # 获取任务节点,查看是否有修改签核者的的任务 + $task = new NodeTask(); + $task->setFormKey($this->currentFlow->getFormKey()) + ->setFlowCode($this->currentFlow->getFlowCode()) + ->setState("OPEN") + ->setPhase("LOAD") + ->setWfCondition('SAME'); + $tasks = TaskManager::getTasks($task); + if (count($tasks) > 0) { + foreach ($tasks as $task) { + $handlerClass = NodeTask::$handlerClasses[constant("NodeTask::" . $task->getTaskType())]; + $handler = new $handlerClass($this->flowContext, $this->formData); + if (method_exists($handler, 'setNextAssignerList')) { + $nextAssigner = $handler->setNextAssignerList($nextAssigner, $task); + } + } + } + } + + $this->nextAssignList = $nextAssigner; + + return $nextAssigner; + } + + /** + *提交前测试表单数据是否满足表达提交条件 + * 1.检测FlowContext对象的以下属性,为空不可提交 + */ + public function submitTest() + { + $errorArray = array(); + #1.检查FlowContext的属性是否都被设置 + $flowContextRequiredProperty = array( + "systemId", "flowId", "formId", "currentAssigner", "flowCode", "nextAssigner", "assignStatus", "assignOpinion", "formKey" + ); + foreach ($this->flowContext as $key => $value) { + if (in_array($key, $flowContextRequiredProperty) and empty($value)) { + array_push($errorArray, "FlowContext:" . $key . " 属性异常. Value:" . $value); + } + } + #2. 当前登陆人员与Sublfow:Current_user 不符合时,不允许提交 + + $currentAssignerId = $this->flowContext->getCurrentUser(); + if (!empty($currentAssignerId) and ID == $currentAssignerId) { + array_push($errorArray, "签核已提交,请勿重复操作."); + } + return $errorArray; + } + + /** + *返回assignStatus + * @param $nextAssigner + * @return string + */ + public function getAssignStatus($nextAssigner) + { + + $htmlOption = "''"; + foreach ($nextAssigner as $assigner) { + + $htmlOption .= ""; + } + + return $htmlOption; + } + + /** + *获取会签部门 + * @param null $flowCode 当前流程的流程码 + * @return array + */ + public function getCounterSignDepart($flowCode = null) + { + $flowCode = empty($flowCode) ? $this->flowContext->getFlowCode() : $flowCode; + /* TODO 从会签节点读取配置的会签属性,并返回成员数组*/ + return null; + } + + /** + * 是否允许拆分 + * @return bool + */ + public function isSplitable() + { + $nodes = $this->workFlowParser->getNextNodes( + $this->currentFlow->getFlowCode(), + [Node::COUNTER_SIGN_TASK] + ); + if (count($nodes) == 0) { + return false; + } + return true; + } + + /** + *1.检查下个节点的类型,为Split节点时 ,返回Split节点下各层节点人员 + */ + public function getSubflowMembers() + { + $nodes = $this->workFlowParser->getNextNodes( + $this->currentFlow->getFlowCode(), + [Node::SPLIT_NODE] + ); + if (count($nodes) == 0) { + return null; + } + $splitNode = $nodes[Node::SPLIT_NODE][0]; + $assigner = $splitNode->getSplitMembers($this->workFlowParser); + return $assigner; + } + + /** + * 获取第一个流程节点 + * @return mixed + */ + public function getFirstFlowCode() + { + + $node = $this->workFlowParser->getFirstNode(); + return $node->getFlowCode(); + } + + /** + * 获取流程的名称 + * @return mixed + */ + public function getFlowName() + { + $flowInfo = $this->workFlowParser->getFlowInfo(); + return $flowInfo['flowName']; + } + + /** + *获取流程版本 + */ + function getFlowVersion() + { + $flowInfo = $this->workFlowParser->getFlowInfo(); + return $flowInfo['version']; + } + + /** + * 获取流程需要的调单数据 + * @return mixed + */ + public function getFormData() + { + return $this->formData; + } + + /** + * 设置表单里面的值 + * @param mixed $formData + */ + public function setFormData($formData) + { + $this->formData = $formData; + $nextUser = empty($formData['next_users']) ? "" : $formData['next_users']; + $assignStatus = empty($formData['assign_status']) ? "" : $formData['assign_status']; + $assignOpinion = empty($formData['assign_opinion']) ? "" : $formData['assign_opinion']; + $currentAssignerId = empty($formData['current_assigner']) ? ID : $formData['current_assigner']; + $this->flowContext->setAssignOpinion($assignOpinion) + ->setNextAssigner($nextUser) + ->setAssignStatus($assignStatus) + ->setFormKey($this->currentFlow->getFormKey()) + ->setFlowCode($this->currentFlow->getFlowCode()) + ->setCurrentUser($currentAssignerId); + } + + /** + * 获取节点的 + * @param $flowCode + * @return String + */ + public function getNodeDescriptions($flowCode) + { + $node = $this->workFlowParser->getNodeByCode($flowCode); + return $node->getNodeDescription(); + } + + /** + * 获取节点的节点 + * @param $flowCode + * @return String + */ + public function getCurrentNode($flowCode = null) + { + $flowCode = empty($flowCode) ? $this->currentFlow->getFlowCode() : $flowCode; + $node = $this->workFlowParser->getNodeByCode($flowCode); + return $node; + } + + /** + * @return mixed + */ + public function getTester() + { + return $this->tester; + } + + /** + * @param mixed $tester + */ + public function setTester($tester) + { + $this->tester = $tester; + } +} diff --git a/workflow/WorkFlowParser.php b/workflow/WorkFlowParser.php new file mode 100644 index 00000000..93e3007e --- /dev/null +++ b/workflow/WorkFlowParser.php @@ -0,0 +1,464 @@ +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; + } +} diff --git a/workflow/impl/CommonFlowNode.php b/workflow/impl/CommonFlowNode.php new file mode 100644 index 00000000..30e9b631 --- /dev/null +++ b/workflow/impl/CommonFlowNode.php @@ -0,0 +1,157 @@ +nodeProperty['flowCode']; + } + + /** + * 获取节点内设置的签核人员列表 + * @return mixed + */ + public function getAssigner() + { + return $this->nodeProperty['assigner']; + } + + /** + * 获取代理人设置 + * @return mixed + */ + public function getAgentSetting() + { + return $this->nodeProperty['agentSetting']; + } + + /** + * 获取签核类别 + * @return mixed + */ + public function getAssignClass() + { + return $this->nodeProperty['assignClass']; + } + + public function getAssignClassMethod() + { + return $this->nodeProperty['assignClassMethod']; + } + + /** + * 获取退回选项 + * @return mixed + */ + public function getBackOption() + { + return $this->nodeProperty['backOption']; + } + + /** + * 获取流程实例 + * @return mixed + */ + public function getFlow() + { + return $this->flow; + } + + /** + * @param mixed $flow + * @return CommonFlowNode + */ + public function setFlow($flow) + { + $this->flow = $flow; + return $this; + } + + /** + * 设置FLow实例 + * @return mixed + */ + public function getFormData() + { + return $this->formData; + } + + /** + * 设置表单数据 + * @param mixed $formData + * @return CommonFlowNode + */ + public function setFormData($formData) + { + $this->formData = $formData; + return $this; + } + + /** + * 检查是否满足流转下一关条件 + * @param $assignClass + * @param $leadCode + * @return bool + */ + function checkTrust($assignClass, $leadCode) + { + $_flag = false; + $flowContext = unserialize($_SESSION['flowContext']); + $assignStatus = $flowContext->getAssignStatus(); + #如果签核节点assign_status 在定义的同层签核节点当中则不可签回 + if (in_array($assignStatus, AssignStatus::$same_level_status)) { + return $_flag; + } + switch ($assignClass) { + case 'A': //无需审核 + $_flag = true; + break; + case 'B': //审核至科长 + $_flag = (in_array($leadCode, array('50', '20', '19', '18', '17', '16', '12', '10')) ? true : false); + + break; + case 'C': //审核至经理 + $_flag = in_array($leadCode, array('20', '19', '18', '17', '16', '12', '10')) ? true : false; + break; + case 'D': //审核至 协理/厂长/总监 + $_flag = in_array($leadCode, array('19', '18', '17', '16', '12', '10')) ? true : false; + break; + case 'E': //审核至副总 + $_flag = in_array($leadCode, array('12', '10')) ? true : false; + break; + case 'F': //审核至总经理 + $_flag = substr($leadCode, 0, 2) == '10' ? true : false; + break; + case 'X': + $method = MethodLoader::getInstanceByMethodString(strip_tags($this->getAssignClassMethod())); + $_assignClass = $method->invokeMethod($this->getFlow(), $this->getFormData()); + $_flag = $this->checkTrust($_assignClass, $leadCode); + break; + default: + $_flag = false; + break; + } + + + return $_flag; + } +} diff --git a/workflow/impl/CounterSignTask.php b/workflow/impl/CounterSignTask.php new file mode 100644 index 00000000..f9e371dc --- /dev/null +++ b/workflow/impl/CounterSignTask.php @@ -0,0 +1,199 @@ +nodeProperty['allowAssign']; + } + + /** + * 转交属性 + */ + public function getPropertyAllowPassTo() + { + return $this->nodeProperty['allowPassTo']; + } + + public function getFlowCode() + { + return $this->nodeProperty['flowCode']; + } + + public function getAssigner() + { + return $this->nodeProperty['assigner']; + } + + public function getMergeOption() + { + return $this->nodeProperty['mergeOption']; + } + + public function getBackOption() + { + return null; + } + + /** + * 1.获取拆分人员 + * @return array + */ + + function getSplitMemers($workFlowParser) + { + $strAssign = $this->getAssigner(); + $assignEmps = array(); + $arr_a = explode('|', $strAssign); + foreach ($arr_a as $key => $value) { + if (empty($value)) { + continue; + } + $arr_b = explode(':', $value); + $val = explode('-', $arr_b[0]); + $arr_c = explode(',', $arr_b[1]); + $str_next_user = ""; + foreach ($arr_c as $key => $value) { + if (empty($value)) { + continue; + } + $str_next_user .= AssignerStringParser::process($value); + } + array_push($assignEmps, array( + $val[0], //assign_status + $str_next_user + )); + } + return $assignEmps; + } + + /** + * 获取签核类别 + */ + public function getAssignClass() + { + $childFlow = SubflowManager::getChildNode($this->flow->formKey); + $leadCode = Employee::lead_code($childFlow['leader_no']); + if ($leadCode >= '80') return 'A'; + if (in_array($leadCode, array('50', '20', '19', '18', '17', '16', '12', '10'))) return 'B'; + if (in_array($leadCode, array('20', '19', '18', '17', '16', '12', '10'))) return 'C'; + if (in_array($leadCode, array('19', '18', '17', '16', '12', '10'))) return 'D'; + if (in_array($leadCode, array('12', '10'))) return 'E'; + if (substr($leadCode, 0, 2) == '10') return 'F'; + } + + /** + * 检查是否满足流转下一关条件 + * @param $assignClass + * @param $leadCode + * @return bool + */ + function checkTrust($assignClass, $leadCode) + { + + # 默认不可签回 + $flowContext = unserialize($_SESSION['flowContext']); + $_flag = false; + $assignStatus = $flowContext->getAssignStatus(); + #如果签核节点assign_status 在定义的同层签核节点当中则不可签回 + if (in_array($assignStatus, AssignStatus::$same_level_status)) { + return $_flag; + } + #获取当前签核者字符串 + $childFlow = SubflowManager::getChildNode($this->flow->formKey); + $currentAssigner = Subflow::getCurrentUser($this->flow->formKey); + if ($currentAssigner == $childFlow['leader_no']) { + #当前人员是被会签人员,可签回 + $_flag = true; + } elseif ($leadCode < Employee::lead_code($currentAssigner)) { + #当前人员的岗位比被会签人员职位高,可签回 + $_flag = true; + } + + return $_flag; + } + + public function getAssignerList(WorkFlowParser $fc) + { + $str_next_user = "00000-各部门,"; + $assigner = array(); + array_push($assigner, array( + "X3", //assign_status + $str_next_user + )); + return $assigner; + } + + /** + * 获取部门的签核人员 + * @param $userId + * @return array + */ + public function getDepartmentalAssignerList($userId) + { + + $leader = Employee::leader($userId); + + $nextAssignerStr = Employee::get_employee($leader, $format = "employee_no-name"); + $nextAssigner = array(0 => array(0 => "F6", 1 => $nextAssignerStr)); + + $subordinates = Employee::subordinates($userId); + + if (count($subordinates) > 0) { + $nextAssignerStr = ""; + foreach ($subordinates as $empl) { + $nextAssignerStr .= Employee::get_employee($empl, $format = "employee_no-name") . ','; + } + array_push($nextAssigner, array(0 => 'FH', 1 => $nextAssignerStr)); + } + return $nextAssigner; + } + + /** + * @return mixed + */ + public function getFlow() + { + return $this->flow; + } + + /** + * @param mixed $flow + * @return CounterSignTask + */ + public function setFlow($flow) + { + $this->flow = $flow; + return $this; + } + + /** + * @return mixed + */ + public function getFormData() + { + return $this->formData; + } + + /** + * @param mixed $formData + * @return CounterSignTask + */ + public function setFormData($formData) + { + $this->formData = $formData; + + return $this; + } +} diff --git a/workflow/impl/EndNode.php b/workflow/impl/EndNode.php new file mode 100644 index 00000000..f540fbd6 --- /dev/null +++ b/workflow/impl/EndNode.php @@ -0,0 +1,78 @@ +请选择'"; + + return $html; + } + + /** + * 检查是否满足流转下一关条件 + * @param $assignClass + * @param $leadCode + * @return bool + */ + function checkTrust($assignClass, $leadCode) + { + $_flag = false; + switch ($assignClass) { + case 'A': //无需审核 + + $_flag = true; + break; + case 'B': //审核至科长 + $_flag = (in_array($leadCode, array('50', '20', '19', '18', '17', '16', '12', '10')) ? true : false); + break; + case 'C': //审核至经理 + $_flag = in_array($leadCode, array('20', '19', '18', '17', '16', '12', '10')) ? true : false; + break; + case 'D': //审核至 协理/厂长/总监 + $_flag = in_array($leadCode, array('19', '18', '17', '16', '12', '10')) ? true : false; + break; + case 'E': //审核至副总 + $_flag = in_array($leadCode, array('12', '10')) ? true : false; + break; + case 'F': //审核至总经理 + $_flag = substr($leadCode, 0, 2) == '10' ? true : false; + break; + case 'X': + $method = MethodLoader::getInstanceByMethodString(strip_tags($this->getAssignClassMethod())); + $_assignClass = $method->invokeMethod($this->getFlow(), $this->getFormData()); + $_flag = $this->checkTrust($_assignClass, $leadCode); + + break; + default: + $_flag = false; + break; + } + return $_flag; + } + +} diff --git a/workflow/impl/FlowNode.php b/workflow/impl/FlowNode.php new file mode 100644 index 00000000..8962b231 --- /dev/null +++ b/workflow/impl/FlowNode.php @@ -0,0 +1,126 @@ +getAssigner(); + $assignEmps = array(); + $arr_a = explode('|', $strAssign); + foreach ($arr_a as $key => $value) { + if (empty($value)) { + continue; + } + $arr_b = explode(':', $value); + $val = explode('-', $arr_b[0]); + $arr_c = explode(',', $arr_b[1]); + $str_next_user = ""; + foreach ($arr_c as $key => $value) { + if (empty($value)) { + continue; + } + if ($value == '00000') { + $str_next_user .= '00000' . '-' . "00000,"; + } else { + $str_next_user .= AssignerStringParser::process($value); + } + } + array_push($assignEmps, array( + $val[0], //assign_status + $str_next_user + )); + } + + return $assignEmps; + } + + /** + * 检查是否满足流转下一关条件 + * @param $assignClass + * @param $leadCode + * @return bool + */ + function checkTrust($assignClass, $leadCode) + { + $_flag = false; + $flowContext = unserialize($_SESSION['flowContext']); + $assignStatus = $flowContext->getAssignStatus(); + #如果签核节点assign_status 在定义的同层签核节点当中则不可签回 + if (in_array($assignStatus, AssignStatus::$same_level_status)) { + return $_flag; + } + switch ($assignClass) { + case 'A': //无需审核 + + $_flag = true; + break; + case 'B': //审核至科长 + $_flag = (in_array($leadCode, array('50', '20', '19', '18', '17', '16', '12', '10','15')) ? true : false); + + break; + case 'C': //审核至经理 + $_flag = in_array($leadCode, array('20', '19', '18', '17', '16', '12', '10','15')) ? true : false; + break; + case 'D': //审核至 协理/厂长/总监 + $_flag = in_array($leadCode, array('19', '18', '17', '16', '12', '10','15')) ? true : false; + break; + case 'E': //审核至副总 + $_flag = in_array($leadCode, array('12', '10')) ? true : false; + break; + case 'F': //审核至总经理 + $_flag = substr($leadCode, 0, 2) == '10' ? true : false; + break; + case 'X': + $method = MethodLoader::getInstanceByMethodString(strip_tags($this->getAssignClassMethod())); + $_assignClass = $method->invokeMethod($this->getFlow(), $this->getFormData()); + $_flag = $this->checkTrust($_assignClass, $leadCode); + break; + default: + $_flag = false; + break; + } + + + return $_flag; + } + + /** + * 获取附加的签核人员 + * @param string $userId + * @return array + */ + public function getDepartmentalAssignerList($userId) + { + + $leader = Employee::leader($userId); + + $nextAssignerStr = Employee::get_employee($leader, $format = "employee_no-name"); + $nextAssigner = array(0 => array(0 => "F6", 1 => $nextAssignerStr)); + + $subordinates = Employee::subordinates($userId); + + if (count($subordinates) > 0) { + $nextAssignerStr = ""; + foreach ($subordinates as $empl) { + $nextAssignerStr .= Employee::get_employee($empl, $format = "employee_no-name") . ','; + + } + array_push($nextAssigner, array(0 => 'FH', 1 => $nextAssignerStr)); + } + return $nextAssigner; + + } + +} diff --git a/workflow/impl/LogicNode.php b/workflow/impl/LogicNode.php new file mode 100644 index 00000000..152aaf42 --- /dev/null +++ b/workflow/impl/LogicNode.php @@ -0,0 +1,125 @@ +nodeProperty['routeMethod']; + if (!empty($methodString)) { + + return MethodLoader::getInstanceByMethodString($methodString); + + } + return null; + } + + /** + *获取流程FLowCode + * @return mixed + */ + public function getFlowCode() + { + $flowContext = unserialize($_SESSION['flowContext']); + $workFlowParser = $flowContext->getWorkFLowParser(); + $prevNodes = $workFlowParser->getPrevLevelNodes(parent::getNodeId(), Node::FLOW_NODE); + $tmpNode = $prevNodes[Node::FLOW_NODE][0]; + $tmpNodeFlowCode = $tmpNode->getFlowCode(); + return $tmpNodeFlowCode; + } + + /** + * 1.检查逻辑节点下层节点,并获取下层节点的assigner + * @param $flowchart + * @return array + */ + public function getAssignerList($flowchart) + { + + + $nodes = $flowchart->getNextLevelNodes(parent::getNodeId()); + $assigner = array(); + foreach (Node::$nodeTypes as $type) { + if (!array_key_exists($type, $nodes)) continue; + foreach ($nodes[$type] as $node) { + if (method_exists($node, 'getAssignerList')) { + $assigner = array_merge((array)$assigner, $node->getAssignerList($flowchart)); + } + } + } + /* $methodString = $this->getMethod(); + if (!empty($methodString)) { + + $_methodInstance = MethodLoader::getInstanceByMethodString($methodString); + + }*/ + return $assigner; + } + + /** + * 获取附加的签核人员 + * @param $userId + * @return array + */ + public function getDepartmentalAssignerList($userId) + { + $leader = Employee::leader($userId); + $nextAssignerStr = Employee::get_employee($leader, $format = "employee_no-name"); + $nextAssigner = array(0 => array(0 => "F6", 1 => $nextAssignerStr)); + return $nextAssigner; + } + + /** + * 检查是否满足流转下一关条件 + * @param $assignClass + * @param $leadCode + * @return bool + */ + function checkTrust($assignClass, $leadCode) + { + $_flag = false; + switch ($assignClass) { + case 'A': //无需审核 + $_flag = true; + break; + case 'B': //审核至科长 + $_flag = (in_array($leadCode, array('50', '20', '19', '18', '17', '16', '12', '10')) ? true : false); + + break; + case 'C': //审核至经理 + $_flag = in_array($leadCode, array('20', '19', '18', '17', '16', '12', '10')) ? true : false; + break; + case 'D': //审核至 协理/厂长/总监 + $_flag = in_array($leadCode, array('19', '18', '17', '16', '12', '10')) ? true : false; + break; + case 'E': //审核至副总 + $_flag = in_array($leadCode, array('12', '10')) ? true : false; + break; + case 'F': //审核至总经理 + $_flag = substr($leadCode, 0, 2) == '10' ? true : false; + break; + case 'X': + + $method = MethodLoader::getInstanceByMethodString(strip_tags($this->getAssignClassMethod())); + $_assignClass = $method->invokeMethod($this->getFlow(), $this->getFormData()); + $_flag = $this->checkTrust($_assignClass, $leadCode); + break; + default: + $_flag = false; + break; + } + return $_flag; + } +} diff --git a/workflow/impl/MailTask.php b/workflow/impl/MailTask.php new file mode 100644 index 00000000..145448aa --- /dev/null +++ b/workflow/impl/MailTask.php @@ -0,0 +1,109 @@ +mailTo = $param["mailTo"]; + $this->mailSubject = $param["mailSubject"]; + $this->mailContent = $param["mailContent"]; + } + + public function doTask() + { + + $mailString = "echo '" . $this->mailContent . "'" + . '| mail -s "$(echo -e " ' . $this->mailSubject . '\nContent-Type: text/html")" ' . $this->mailTo . '@yungtay.com.cn'; + system($mailString); + } + /** + * @return mixed + */ + public function getMailFrom() + { + return $this->mailFrom; + } + + /** + * @param mixed $mailFrom + * @return MailTask + */ + public function setMailFrom($mailFrom) + { + $this->mailFrom = $mailFrom; + return $this; + } + + /** + * @return mixed + */ + public function getMailTo() + { + return $this->mailTo; + } + + /** + * @param mixed $mailTo + * @return MailTask + */ + public function setMailTo($mailTo) + { + $this->mailTo = $mailTo; + return $this; + } + + /** + * @return mixed + */ + public function getMailSubject() + { + return $this->mailSubject; + } + + /** + * @param mixed $mailSubject + * @return MailTask + */ + public function setMailSubject($mailSubject) + { + $this->mailSubject = $mailSubject; + return $this; + } + + /** + * @return mixed + */ + public function getMailContent() + { + return $this->mailContent; + } + + /** + * @param mixed $mailContent + * @return MailTask + */ + public function setMailContent($mailContent) + { + $this->mailContent = $mailContent; + return $this; + } +} diff --git a/workflow/impl/MergeNode.php b/workflow/impl/MergeNode.php new file mode 100644 index 00000000..7cf2c415 --- /dev/null +++ b/workflow/impl/MergeNode.php @@ -0,0 +1,43 @@ +nodeProperty['mergeOption']; + } + + /** + * 1.检查逻辑节点下层节点,并获取下层节点的assigner + * @param WorkFlowParser $workFlowParser + * @return array + */ + public function getAssignerList(WorkFlowParser $workFlowParser) + { + + $nodes = $workFlowParser->getNextLevelNodes(parent::getNodeId()); + $assigner = array(); + foreach (Node::$nodeTypes as $type) { + if (!array_key_exists($type, $nodes)) continue; + foreach ($nodes[$type] as $node) { + if (method_exists($node, 'getAssignerList')) { + $assigner = array_merge((array)$assigner, $node->getAssignerList($workFlowParser)); + } + } + } + return $assigner; + } + + +} \ No newline at end of file diff --git a/workflow/impl/Node.php b/workflow/impl/Node.php new file mode 100644 index 00000000..f031c7e1 --- /dev/null +++ b/workflow/impl/Node.php @@ -0,0 +1,84 @@ +"StartNode", + self::TASK_NODE => "TaskNode", + self::LOGIC_NODE => "LogicNode", + self::SPLIT_NODE => "SplitNode", + self::FLOW_NODE => "FlowNode", + self::MERGE_NODE => "MergeNode", + self::END_NODE => "EndNode", + self::COUNTER_SIGN_TASK => "CounterSignTask", + self::COUNTER_SIGN_SUBTASK => "CounterSignSubtask" + ); + static $nodeTypes = array( + self::START_NODE, + self::TASK_NODE, + self::LOGIC_NODE, + self::SPLIT_NODE, + self::FLOW_NODE, + self::MERGE_NODE, + self::END_NODE, + self::COUNTER_SIGN_TASK, + self::COUNTER_SIGN_SUBTASK + ); + static $handlerClasses = array( + self::START_NODE=>"StartNodeHandler", + self::TASK_NODE => "TaskNodeHandler", + self::LOGIC_NODE => "LogicNodeHandler", + self::SPLIT_NODE => "SplitNodeHandler", + self::FLOW_NODE => "FlowNodeHandler", + self::MERGE_NODE => "MergeNodeHandler", + self::END_NODE => "EndNodeHandler", + self::COUNTER_SIGN_TASK => "CounterSignTaskHandler", + self::COUNTER_SIGN_SUBTASK => "CounterSignSubtaskHandler" + ); + protected $nodeProperty; + + /** + *返回节点类型 + * @param $param + */ + function __construct($param) + { + $this->nodeProperty = $param; + } + + public function getType() + { + return $this->nodeProperty['nodeType']; + } + public function getNodeId() + { + return $this->nodeProperty['nodeId']; + } + public function getNodeDescription() + { + return $this->nodeProperty['desc']; + } +} diff --git a/workflow/impl/NoticeTask.php b/workflow/impl/NoticeTask.php new file mode 100644 index 00000000..6041b894 --- /dev/null +++ b/workflow/impl/NoticeTask.php @@ -0,0 +1,54 @@ +noticeList = $param["noticeList"]; + $this->noticeTitle = $param["noticeTitle"]; + $this->noticeUrl = $param["noticeUrl"]; + } + + public function doTask() + { + + return 0; + // return $mailString; + } + + /** + * 设置任务的属性 + * @param $objProperty + */ + public function setTaskProperty($objProperty) + { + } + + /** + * 任务执行之前 + */ + public function beforeDoTask() + { + } + + /** + * 任务执行之后 + */ + public function afterDoTask() + { + } +} diff --git a/workflow/impl/SplitNode.php b/workflow/impl/SplitNode.php new file mode 100644 index 00000000..510d1529 --- /dev/null +++ b/workflow/impl/SplitNode.php @@ -0,0 +1,87 @@ +getAllNode(Node::MERGE_NODE); + if (count($mergeNodes) == 0) return $assigners; + $subFlowNodes = $workFlowParser->getNextLevelNodes(parent::getNodeId(), Node::FLOW_NODE); + if (count($subFlowNodes) == 0) return $assigners; + foreach ($mergeNodes[Node::MERGE_NODE] as $mergeNode) { + + $pathLength[$mergeNode->getNodeId()] = 0; + foreach ($subFlowNodes[Node::FLOW_NODE] as $flowNode) { + $path = $workFlowParser->getMinLengthBetweenNode($mergeNode->getNodeId(), $flowNode->getNodeId()); + + if (count($path) == 0) { //不存在路径,设置为极大值 + $pathLength[$mergeNode->getNodeId()] = PHP_INT_MAX; + break; + } + $pathLength[$mergeNode->getNodeId()] += count($pathLength[$mergeNode->getNodeId()]) + 1; + } + + } + if (min($pathLength) == PHP_INT_MAX) return $assigners; + $MinLengthPathNode = $workFlowParser->getNodeByNodeId(array_search(min($pathLength), $pathLength)); + $SecondAssigners = $MinLengthPathNode->getAssignerList($workFlowParser); + if (count($SecondAssigners) == 0) return $assigners; + return $SecondAssigners; + + } + + /** + * 1.检查逻辑节点下层节点,并获取下层节点的assigner + * @param WorkFlowParser $workFlowParser + * @return array + */ + + function getSplitMembers(WorkFlowParser $workFlowParser) + { + + $assigners = $this->getNextAssignerList($workFlowParser); + foreach ($assigners as $key => $assigner) { + $arr = explode('-', $assigner[1]); + $_depart = Depart::depart_name(Employee::f_return_depart($arr[0])); + $assigners[$key] = $_depart . '-' . $arr[1]; + } + return $assigners; + } + + /** + * @param WorkFlowParser $workFlowParser + * @return array + */ + function getNextAssignerList(WorkFlowParser $workFlowParser) + { + $nodes = $workFlowParser->getNextLevelNodes(parent::getNodeId()); + $assigners = array(); + foreach (Node::$nodeTypes as $type) { + if (!array_key_exists($type, $nodes)) continue; + foreach ($nodes[$type] as $node) { + if (method_exists($node, 'getAssignerList')) { + $assigners = array_merge((array)$assigners, $node->getAssignerList($workFlowParser)); + } + } + } + return $assigners; + } + +} diff --git a/workflow/impl/StartNode.php b/workflow/impl/StartNode.php new file mode 100644 index 00000000..469e62cb --- /dev/null +++ b/workflow/impl/StartNode.php @@ -0,0 +1,128 @@ +nodeProperty['backOption']) + ? null : $this->nodeProperty['backOption']; + } + + public function getAssignerList() + { + $strAssigner = $this->getAssigner(); + //B4-退回:73376,73502,73396|A4-待评估:73376,73502| + $assignerList = array(); + $arr_a = explode('|', $strAssigner); + foreach ($arr_a as $key => $value) { + if (empty($value)) { + continue; + } + $arr_b = explode(':', $value); + $val = explode('-', $arr_b[0]); + $arr_c = explode(',', $arr_b[1]); + $strNextUser = ""; + foreach ($arr_c as $key => $value) { + if (empty($value)) { + continue; + } + if ($value == '00000') { + $strNextUser .= "00000" . '-' . "00000,"; + } else { + $strNextUser .= AssignerStringParser::process($value); + } + } + array_push($assignerList, array($val[0], $strNextUser)); + } + return $assignerList; + } + + /** + * @return string + */ + public function getAssignStatus() + { + //B4-退回:73376,73502,73396|A4-待评估:73376,73502| + $strAssigner = $this->getAssigner(); + $html = "''"; + $arr_a = explode('|', $strAssigner); + foreach ($arr_a as $key => $value) { + if (empty($value)) { + continue; + } + $arr_b = explode(':', $value); //B4-退回:73376,73502,73396 + $val = explode('-', $arr_b[0]); + + $html .= ""; + } + return $html; + } + + /** + * 获取附加的签核人员 + * @param $userId + * @return array + */ + public function getDepartmentalAssignerList($userId) + { + $leader = Employee::leader($userId); + $nextAssignerStr = Employee::get_employee($leader, $format = "employee_no-name"); + $nextAssigner = array(0 => array(0 => "F6", 1 => $nextAssignerStr)); + return $nextAssigner; + } + + /** + * 检查是否满足流转下一关条件 + * @param $assignClass + * @param $leadCode + * @return bool + */ + function checkTrust($assignClass, $leadCode) + { + $_flag = false; + switch ($assignClass) { + case 'A': //无需审核 + + $_flag = true; + break; + case 'B': //审核至科长 + $_flag = (in_array($leadCode, array('50', '20', '19', '18', '17', '16', '15', '12', '11', '10')) ? true : false); + + break; + case 'C': //审核至经理 + $_flag = in_array($leadCode, array('20', '19', '18', '17', '15', '16', '12', '11', '10')) ? true : false; + break; + case 'D': //审核至 协理/厂长/总监 + $_flag = in_array($leadCode, array('19', '18', '17', '16', '15', '12', '11', '10')) ? true : false; + break; + case 'E': //审核至副总 + $_flag = in_array($leadCode, array('12', '10')) ? true : false; + break; + case 'F': //审核至总经理 + $_flag = substr($leadCode, 0, 2) == '10' ? true : false; + break; + case 'X': + $method = MethodLoader::getInstanceByMethodString(strip_tags(html_entity_decode($this->getAssignClassMethod()))); + // var_dump($this->getFormData()); + $_assignClass = $method->invokeMethod($this->getFlow(), $this->getFormData()); + $_flag = $this->checkTrust($_assignClass, $leadCode); + + break; + default: + $_flag = false; + break; + } + return $_flag; + } +} diff --git a/workflow/interface/IFlow.php b/workflow/interface/IFlow.php new file mode 100644 index 00000000..1d3d51e3 --- /dev/null +++ b/workflow/interface/IFlow.php @@ -0,0 +1,8 @@ + \ No newline at end of file diff --git a/workflow/interface/IRouter.php b/workflow/interface/IRouter.php new file mode 100644 index 00000000..a7fa856f --- /dev/null +++ b/workflow/interface/IRouter.php @@ -0,0 +1,11 @@ + \ No newline at end of file diff --git a/workflow/lib/AssignStatus.php b/workflow/lib/AssignStatus.php new file mode 100644 index 00000000..6fc00e2c --- /dev/null +++ b/workflow/lib/AssignStatus.php @@ -0,0 +1,29 @@ +getFormKey(), $as_array = true, $code); + $str_next_user = ""; + foreach ($records as $record) { + $tmp_str = Employee::get_employee($record['assigner'], $format); + $str_next_user .= $tmp_str . $delimiter; + } + return $str_next_user; + + } + + /** + * 处理未定义的情况 + * @return string + */ + public static function processUndefined($function) + { + return "调用了不存在的处理函数:" . $function; + } + +} \ No newline at end of file diff --git a/workflow/lib/DB.php b/workflow/lib/DB.php new file mode 100644 index 00000000..85459c13 --- /dev/null +++ b/workflow/lib/DB.php @@ -0,0 +1,209 @@ + array('host' => 'db-104.coowo.com', 'db_name' => 'appwms', 'user' => 'masadaroot', 'pwd' => 'x6h5E5p#u8y') + ); + public static $instance; + /** + * ? + * + * @param string $db + * @return object + */ + public static function instance($db = 'default') + { + + $dbh = new PDO("mysql:host=" . self::$ds[$db]['host'] . ";dbname=appwms" . ";charset=utf8", self::$ds[$db]['user'], self::$ds[$db]['pwd']); + $dbh->setAttribute(PDO::ATTR_CASE, PDO::CASE_LOWER); + return $dbh; + } + /** + * ?insert + * + * @param [String] $table_name + * @param [Array] $cols + * @param [Array] $values + * @param string $db + * @return void + */ + public static function insert_batch($table_name, $cols, $values, $db = 'default') + { + $_sql = 'insert into ' . $table_name . '(' . implode(",", $cols) . ')'; + $_vsql = array(); + foreach ($values as $value) { + $_vsql[] = 'select ' . implode(",", $value) . 'from dual'; + } + $_sql .= implode(' Union All ', $_vsql); + // self::query($_sql, $db); + self::instance($db)->exec($_sql); + } + /** + * insert + * + * @param [type] $table_name + * @param [type] $data + * @param string $db + * @return void + */ + public static function insert_table($table_name, $data, $db = 'default') + { + + + // $stmt->debugDumpParams(); + + $fields = array_keys($data); + + $meta = self::metadata($table_name, array_keys($data), $db); + // var_dump( $meta); + + foreach ($fields as $f) { + + if ($meta[$f] == 'LONG' || $meta[$f] == 'NEWDECIMAL') { + $data[$f] = (int) $data[$f]; + } elseif ($meta[$f] == 'DATETIME' && empty($data[$f])) { + $data[$f] = 'NULL'; + } else { + // var_dump( $data[$f]); + // if( is_array($data[$f])){ echo "$table_name " ; echo "$f ";}; + + $data[$f] = "'" . $data[$f] . "'"; + $data[$f] = $data[$f]; + } + } + + //foreach ($fields as $f) { + + $_sql = "insert into " . $table_name . "(" . implode(",", array_keys($data)) . ") values (" . implode(",", array_values($data)) . " )"; +//echo $_sql; + self::instance($db)->exec($_sql); + // $stmt->debugDumpParams(); + + + + } + /** + * + * + * @param [String] $table_name + * @param [Array] $data + * @param [String] $data + * @param string $db + * @return void + */ + public static function update_table($table_name, $data, $where, $db = 'default') + { + $fields = array_keys($data); + + $meta = self::metadata($table_name, array_keys($data), $db); + // var_dump( $meta); + + foreach ($fields as $f) { + + if ($meta[$f] == 'LONG') { + $data[$f] = (int) $data[$f]; + } else if ($meta[$f] == 'NEWDECIMAL') { + $data[$f] = (float) $data[$f]; + } elseif ($meta[$f] == 'DATETIME' && empty($data[$f])) { + $data[$f] = NULL; + } else { + $data[$f] = $data[$f]; + $data[$f] = $data[$f]; + } + } + + + + if (empty($where)) { + return false; + } + $sql = "update $table_name set "; + $i = 0; + foreach ($data as $key => $val) { + $sql .= $i++ > 0 ? " , $key=:$key " : " $key=:$key "; + $value[$key] = $val; + } + // var_dump($value); + $sql .= " where " . $where; + $stmt = self::instance($db)->prepare($sql); + + $stmt->execute($value); + // $stmt->debugDumpParams(); + } + + /** + * sql + * + * @param [String] $sql + * @param string $db + * @return void + */ + public static function fields($sql, $db = 'default') + { + return self::query($sql)->fetch(PDO::FETCH_BOTH); + } + /** + * ?,as_array array? + * + * @param [String] $sql + * @param boolean $as_array + * @param string $db + * @return mixed + */ + public static function result($sql, $as_array = true, $db = 'default') + { + // echo $sql; + $resource = self::query($sql, $db); + + return $as_array == false ? $resource->fetchAll(PDO::FETCH_OBJ) : $resource->fetchAll(PDO::FETCH_BOTH); + } + /** + *sql? + * + * @param [String] $sql + * @return [int] + */ + public static function effect_num($sql, $db = 'default') + { + return count(self::query($sql, $db)->fetchAll()); + } + public static function query($sql, $db = 'default') + { + + // echo $sql; + $res = self::instance($db)->prepare($sql); + + if (!$res) { + // var_dump($res->errorInfo()); + } else { + $res->execute(); + + return $res; + } + } + public function escape($filed) + { + } + + /* + * 获取列的元数据 + * + * @param [type] $tablename + * @return void + */ + public static function metadata($tablename = null, $col = array(), $db = 'default') + { + $column_types = array(); + + $stmt = self::query("SELECT " . implode(",", array_values($col)) . " FROM " . $tablename . " limit 0,1"); + for ($i = 0; $i < $stmt->columnCount(); $i++) { + $meta[$i] = $stmt->getColumnMeta($i); + + $column_types[$meta[$i]['name']] = $meta[$i]['native_type']; + } + + return $column_types; + } +} diff --git a/workflow/lib/Depart.php b/workflow/lib/Depart.php new file mode 100644 index 00000000..e1496055 --- /dev/null +++ b/workflow/lib/Depart.php @@ -0,0 +1,68 @@ +employee_no, + $this->depart_no, + $this->name, + $this->lead_code, + $this->position_code, + $this->mail, + $this->mail_server + ) = DB::fields("SELECT EMPLOYEE_NO,DEPART_NO,NAME,LEAD_CODE,POSITION_CODE,MAIL,MAIL_SERVER + FROM employee + WHERE EMPLOYEE_NO='" . $employee_no . "' + "); + } + + static $allowFormatWord = array( + "employee_no", + "name", + "depart_no", + "position", + "depart_name" + ); + + /** + * 获取领导 + * + * @param String $employee_no + * @return void + */ + public static function leader($employee_no) + { + $_sql = "select f_return_leader('" . $employee_no . "') LEADER from dual"; + list($_leader) = DB::fields($_sql); + return $_leader; + } + + /** + * 获取lead_code + * + * @param String $employee_no + * @return void + */ + public static function lead_code($employee_no) + { + $_sql = "select lead_code from employee where employee_no='" . $employee_no . "'"; + list($_lead_code) = DB::fields($_sql); + return $_lead_code; + } + + /** + * 姓名 + * + * @param String $employee_no + * @return void + */ + public static function name($employee_no) + { + $_sql = "select name from employee where employee_no='" . $employee_no . "'"; + list($_name) = DB::fields($_sql, 'ibmora'); + + return $_name; + } + + /** + * 员工号 + * + * @param String $employee_no + * @return void + */ + public static function get_employee_no($employee_no) + { + + return $employee_no; + } + + public static function get_position_name($employee_no) + { + if (Employee::lead_code($employee_no) == '90') return ""; + return Code::getContent("lead_code", Employee::lead_code($employee_no)); + } + + /** + * 获取员工部门 + * + * @return void + */ + public static function f_return_depart($employee_no) + { + $_sql = "select depart_no from employee where employee_no='" . $employee_no . "'"; + list($_depart) = DB::fields($_sql); + return $_depart; + } + + /** + * 获取员工部门名称 + * + * @return void + */ + public static function f_return_depart_name($employee_no) + { + $_depart = self::f_return_depart($employee_no); + + return Depart::depart_name($_depart); + } + + /** + * 获取下属 + * + * @param String $employee_no + * @return void|array + */ + public static function subordinates($employee_no) + { + $depart = self::f_return_depart($employee_no); + $depart = rtrim($depart, 0); + $_sql = "select employee_no from employee where + depart_no like '" . $depart . "%' + and employee_no!='" . $employee_no . "' + and lead_code >'" . self::lead_code($employee_no) . "' "; + // echo $_sql; + $_arr = array(); + $result = DB::result($_sql, true); + + foreach ($result as $row) { + if (!empty($row['employee_no'])) { + array_push($_arr, $row['employee_no']); + } + } + return $_arr; + } + + /** + * @param $employee_no + * @param string $format + * @return mixed|string + */ + public static function get_employee($employee_no, $format = "employee_no-name position") + { + $tmp_str = $format; + if ($employee_no == '00000' or empty($employee_no)) { + return '00000'; + } + $_sql = " select employee_no,name,depart_no,f_return_depart_name(depart_no) depart_name, + f_return_content('lead_code',lead_code) position from employee where employee_no='" . $employee_no . "'"; + + $result = DB::result($_sql, true); + + foreach (self::$allowFormatWord as $word) { + $tmp_str = str_replace($word, $result[0][$word], $tmp_str); + } + return $tmp_str; + } +} diff --git a/workflow/lib/Logger.php b/workflow/lib/Logger.php new file mode 100644 index 00000000..809e5294 --- /dev/null +++ b/workflow/lib/Logger.php @@ -0,0 +1,400 @@ +logInfo('Returned a million search results'); //Prints to the log file + * $log->logFatal('Oh dear.'); //Prints to the log file + * $log->logDebug('x = 5'); //Prints nothing due to current severity threshhold + */ + +/** + * Class documentation + */ +class Logger +{ + + const EMERG = 0; // Emergency: system is unusable + const ALERT = 1; // Alert: action must be taken immediately + const CRIT = 2; // Critical: critical conditions + const ERR = 3; // Error: error conditions + const WARN = 4; // Warning: warning conditions + const NOTICE = 5; // Notice: normal but significant condition + const INFO = 6; // Informational: informational messages + const DEBUG = 7; // Debug: debug messages + + //custom logging level + /** + * Log nothing at all + */ + const OFF = 8; + /** + * Alias for CRIT + * @deprecated + */ + const FATAL = 2; + + /** + * Internal status codes + */ + const STATUS_LOG_OPEN = 1; + const STATUS_OPEN_FAILED = 2; + const STATUS_LOG_CLOSED = 3; + + /** + * We need a default argument value in order to add the ability to easily + * print out objects etc. But we can't use NULL, 0, FALSE, etc, because those + * are often the values the developers will test for. So we'll make one up. + */ + const NO_ARGUMENTS = 'Logger::NO_ARGUMENTS'; + + /** + * Current status of the log file + * @var integer + */ + private $_logStatus = self::STATUS_LOG_CLOSED; + /** + * Holds messages generated by the class + * @var array + */ + private $_messageQueue = array(); + /** + * Path to the log file + * @var string + */ + private $_logFilePath = null; + /** + * Current minimum logging threshold + * @var integer + */ + private $_severityThreshold = self::INFO; + /** + * This holds the file handle for this instance's log file + * @var resource + */ + private $_fileHandle = null; + + /** + * Standard messages produced by the class. Can be modified for il8n + * @var array + */ + private $_messages = array( + //'writefail' => 'The file exists, but could not be opened for writing. Check that appropriate permissions have been set.', + 'writefail' => 'The file could not be written to. Check that appropriate permissions have been set.', + 'opensuccess' => 'The log file was opened successfully.', + 'openfail' => 'The file could not be opened. Check permissions.', + ); + + /** + * Default severity of log messages, if not specified + * @var integer + */ + private static $_defaultSeverity = self::DEBUG; + /** + * Valid PHP date() format string for log timestamps + * @var string + */ + private static $_dateFormat = 'Y-m-d G:i:s'; + /** + * Octal notation for default permissions of the log file + * @var integer + */ + private static $_defaultPermissions = 0777; + /** + * Array of Logger instances, part of Singleton pattern + * @var array + */ + private static $instances = array(); + + /** + * Partially implements the Singleton pattern. Each $logDirectory gets one + * instance. + * + * @param string $logDirectory File path to the logging directory + * @param integer $severity One of the pre-defined severity constants + * @return Logger + */ + public static function instance($logDirectory = false, $severity = false) + { + if ($severity === false) { + $severity = self::$_defaultSeverity; + } + + if ($logDirectory === false) { + if (count(self::$instances) > 0) { + return current(self::$instances); + } else { + $logDirectory = dirname(__FILE__); + } + } + + if (in_array($logDirectory, self::$instances)) { + return self::$instances[$logDirectory]; + } + + self::$instances[$logDirectory] = new self($logDirectory, $severity); + + return self::$instances[$logDirectory]; + } + + /** + * Class constructor + * + * @param string $logDirectory File path to the logging directory + * @param integer $severity One of the pre-defined severity constants + * @return void + */ + public function __construct($logDirectory, $severity) + { + $logDirectory = rtrim($logDirectory, '\\/'); + + if ($severity === self::OFF) { + return; + } + + $this->_logFilePath = $logDirectory + . DIRECTORY_SEPARATOR + . 'log_' + . date('Y-m-d') + . '.txt'; + + $this->_severityThreshold = $severity; + if (!file_exists($logDirectory)) { + mkdir($logDirectory, self::$_defaultPermissions, true); + } + + if (file_exists($this->_logFilePath) && !is_writable($this->_logFilePath)) { + $this->_logStatus = self::STATUS_OPEN_FAILED; + $this->_messageQueue[] = $this->_messages['writefail']; + return; + } + + if (($this->_fileHandle = fopen($this->_logFilePath, 'a'))) { + $this->_logStatus = self::STATUS_LOG_OPEN; + $this->_messageQueue[] = $this->_messages['opensuccess']; + } else { + $this->_logStatus = self::STATUS_OPEN_FAILED; + $this->_messageQueue[] = $this->_messages['openfail']; + } + } + + /** + * Class destructor + */ + public function __destruct() + { + if ($this->_fileHandle) { + fclose($this->_fileHandle); + } + } + /** + * Writes a $line to the log with a severity level of DEBUG + * + * @param string $line Information to log + * @return void + */ + public function logDebug($line, $args = self::NO_ARGUMENTS) + { + $this->log($line, self::DEBUG); + } + + /** + * Returns (and removes) the last message from the queue. + * @return string + */ + public function getMessage() + { + return array_pop($this->_messageQueue); + } + + /** + * Returns the entire message queue (leaving it intact) + * @return array + */ + public function getMessages() + { + return $this->_messageQueue; + } + + /** + * Empties the message queue + * @return void + */ + public function clearMessages() + { + $this->_messageQueue = array(); + } + + /** + * Sets the date format used by all instances of Logger + * + * @param string $dateFormat Valid format string for date() + */ + public static function setDateFormat($dateFormat) + { + self::$_dateFormat = $dateFormat; + } + + /** + * Writes a $line to the log with a severity level of INFO. Any information + * can be used here, or it could be used with E_STRICT errors + * + * @param string $line Information to log + * @return void + */ + public function logInfo($line, $args = self::NO_ARGUMENTS) + { + $this->log($line, self::INFO, $args); + } + + /** + * Writes a $line to the log with a severity level of NOTICE. Generally + * corresponds to E_STRICT, E_NOTICE, or E_USER_NOTICE errors + * + * @param string $line Information to log + * @return void + */ + public function logNotice($line, $args = self::NO_ARGUMENTS) + { + $this->log($line, self::NOTICE, $args); + } + + /** + * Writes a $line to the log with a severity level of WARN. Generally + * corresponds to E_WARNING, E_USER_WARNING, E_CORE_WARNING, or + * E_COMPILE_WARNING + * + * @param string $line Information to log + * @return void + */ + public function logWarn($line, $args = self::NO_ARGUMENTS) + { + $this->log($line, self::WARN, $args); + } + + /** + * Writes a $line to the log with a severity level of ERR. Most likely used + * with E_RECOVERABLE_ERROR + * + * @param string $line Information to log + * @return void + */ + public function logError($line, $args = self::NO_ARGUMENTS) + { + $this->log($line, self::ERR, $args); + } + + /** + * Writes a $line to the log with a severity level of FATAL. Generally + * corresponds to E_ERROR, E_USER_ERROR, E_CORE_ERROR, or E_COMPILE_ERROR + * + * @param string $line Information to log + * @return void + * @deprecated Use logCrit + */ + public function logFatal($line, $args = self::NO_ARGUMENTS) + { + $this->log($line, self::FATAL, $args); + } + + /** + * Writes a $line to the log with a severity level of ALERT. + * + * @param string $line Information to log + * @return void + */ + public function logAlert($line, $args = self::NO_ARGUMENTS) + { + $this->log($line, self::ALERT, $args); + } + + /** + * Writes a $line to the log with a severity level of CRIT. + * + * @param string $line Information to log + * @return void + */ + public function logCrit($line, $args = self::NO_ARGUMENTS) + { + $this->log($line, self::CRIT, $args); + } + + /** + * Writes a $line to the log with a severity level of EMERG. + * + * @param string $line Information to log + * @return void + */ + public function logEmerg($line, $args = self::NO_ARGUMENTS) + { + $this->log($line, self::EMERG, $args); + } + + /** + * Writes a $line to the log with the given severity + * + * @param string $line Text to add to the log + * @param integer $severity Severity level of log message (use constants) + */ + public function log($line, $severity, $args = self::NO_ARGUMENTS) + { + if ($this->_severityThreshold >= $severity) { + $status = $this->_getTimeLine($severity); + + $line = "$status $line"; + + if ($args !== self::NO_ARGUMENTS) { + /* Print the passed object value */ + $line = $line . '; ' . var_export($args, true); + } + + $this->writeFreeFormLine($line . PHP_EOL); + } + } + + /** + * Writes a line to the log without prepending a status or timestamp + * + * @param string $line Line to write to the log + * @return void + */ + public function writeFreeFormLine($line) + { + if ( + $this->_logStatus == self::STATUS_LOG_OPEN + && $this->_severityThreshold != self::OFF + ) { + if (fwrite($this->_fileHandle, $line) === false) { + $this->_messageQueue[] = $this->_messages['writefail']; + } + } + } + + private function _getTimeLine($level) + { + $time = date(self::$_dateFormat); + + switch ($level) { + case self::EMERG: + return "$time - EMERG -->"; + case self::ALERT: + return "$time - ALERT -->"; + case self::CRIT: + return "$time - CRIT -->"; + case self::FATAL: # FATAL is an alias of CRIT + return "$time - FATAL -->"; + case self::NOTICE: + return "$time - NOTICE -->"; + case self::INFO: + return "$time - INFO -->"; + case self::WARN: + return "$time - WARN -->"; + case self::DEBUG: + return "$time - DEBUG -->"; + case self::ERR: + return "$time - ERROR -->"; + default: + return "$time - LOG -->"; + } + } +} diff --git a/workflow/lib/MethodLoader.php b/workflow/lib/MethodLoader.php new file mode 100644 index 00000000..275fc8d4 --- /dev/null +++ b/workflow/lib/MethodLoader.php @@ -0,0 +1,41 @@ +methodString = $methodString; + } + public function invokeMethod($flow, $form) + { + //function[\s\n]+(\S+)[\s\n]*\( + preg_match_all("/function[\s\n]+(\S+)[\s\n]*\(/", $this->methodString, $arr); + eval($this->methodString . ";"); + $func=$arr[1][0]; + return $func($flow, $form); + } + }; + + return $obj; + } +} diff --git a/workflow/model/Assign.php b/workflow/model/Assign.php new file mode 100644 index 00000000..c434bbfd --- /dev/null +++ b/workflow/model/Assign.php @@ -0,0 +1,254 @@ +form_key; + } + + /** + * @param null $form_key + * @return Assign + */ + public function setFormKey($form_key) + { + $this->form_key = $form_key; + return $this; + } + + /** + * @return int + */ + public function getSeq() + { + return $this->seq; + } + + /** + * @param int $seq + * @return Assign + */ + public function setSeq($seq) + { + $this->seq = $seq; + return $this; + } + + /** + * @return mixed + */ + public function getAssigner() + { + return $this->assigner; + } + + /** + * @param mixed $assigner + * @return Assign + */ + public function setAssigner($assigner) + { + $this->assigner = $assigner; + return $this; + } + + /** + * @return mixed + */ + public function getAssignStatus() + { + return $this->assign_status; + } + + /** + * @param mixed $assign_status + * @return Assign + */ + public function setAssignStatus($assign_status) + { + $this->assign_status = $assign_status; + return $this; + } + + /** + * @return mixed + */ + public function getAssignDate() + { + return $this->assign_date; + } + + /** + * @param mixed $assign_date + * @return Assign + */ + public function setAssignDate($assign_date) + { + $this->assign_date = $assign_date; + return $this; + } + + /** + * @return mixed + */ + public function getAssignOpinion() + { + return $this->assign_opinion; + } + + /** + * @param mixed $assign_opinion + * @return Assign + */ + public function setAssignOpinion($assign_opinion) + { + $this->assign_opinion = $assign_opinion; + return $this; + } + + /** + * @return mixed + */ + public function getFlowCode() + { + return $this->flow_code; + } + + /** + * @param mixed $flow_code + * @return Assign + */ + public function setFlowCode($flow_code) + { + $this->flow_code = $flow_code; + return $this; + } + + /** + * @return mixed + */ + public function getFlowCodeSeq() + { + return $this->flow_code_seq; + } + + /** + * @param mixed $flow_code_seq + * @return Assign + */ + public function setFlowCodeSeq($flow_code_seq) + { + $this->flow_code_seq = $flow_code_seq; + return $this; + } + + /** + * @return mixed + */ + public function getRealAssigner() + { + return $this->real_assigner; + } + + /** + * @param mixed $real_assigner + * @return Assign + */ + public function setRealAssigner($real_assigner) + { + $this->real_assigner = $real_assigner; + return $this; + } + + + /** + * @param null $formKey + */ + public function __construct($formKey = null) + { + + $this->form_key = $formKey; + + list($seq) = DB::fields("SELECT max(seq) FROM assign + where form_key ='$formKey'"); + $this->seq = empty($seq) ? 0 : $seq; + } + + /** + * @param null $formKey + * @param string $as_array + * @param string $code + * @param string $assign_status + * @return array + */ + public static function get_records($formKey = null, $as_array = "true", $code = '%', $assign_status = '%') + { + try { + $sql = "select seq,assigner,assign_opinion, assign_date assign_date + ,lead_code,f_return_content('lead_code',lead_code) position_name,assign_status,flow_code, + f_return_depart(assigner) assign_depart ,f_return_depart_name(f_return_depart(assigner)) assign_depart_name + from + assign a,employee b where + a.assigner =b.employee_no + and assign_status like '" . $assign_status . "%' + and form_key = '" . $formKey . "' and flow_code like '" . $code . "%' order by assign_date asc"; + // echo $sql; + return DB::result($sql, $as_array); + + } catch (Exception $e) { + echo 'Caught exception: ', $e->getMessage(), "\n"; + return null; + } + + } + + public static function get_lastest_record($formKey, $code) + { + try { + $sql = "select seq,assigner,assign_opinion, assign_date assign_date,lead_code, + f_return_content('lead_code',lead_code) position_name,assign_status,flow_code, + f_return_depart(assigner) assign_depart ,f_return_depart_name(f_return_depart(assigner)) assign_depart_name + from + assign a,employee b where + a.assigner =b.employee_no + and form_key = '" . $formKey . "' and seq in( + select max(seq) from assign where form_key = '" . $formKey . "' + and flow_code like '" . $code . "%' + ) "; + $result = DB::result($sql); + return $result[0]; + + } catch (Exception $e) { + echo 'Caught exception: ', $e->getMessage(), "\n"; + return null; + } + } + + public function insert() + { + DB::insert_table("assign", array( + "form_key" => $this->form_key, + "seq" => $this->seq + 1, + "assigner" => $this->assigner, + "assign_status" => $this->assign_status, + "assign_opinion" => $this->assign_opinion, + "flow_code" => $this->flow_code, + "flow_code_seq" => $this->flow_code_seq, + "real_assigner" => $this->real_assigner + )); + } +} \ No newline at end of file diff --git a/workflow/model/Code.php b/workflow/model/Code.php new file mode 100644 index 00000000..884af59d --- /dev/null +++ b/workflow/model/Code.php @@ -0,0 +1,17 @@ +form_key = self::getNewFormKey(); + } else { + + list( + $this->system_id, + $this->flow_id, + $this->form_id, + $this->form_key, + $this->flow_code, + $this->flow_code_seq, + $this->back_code + ) + = DB::fields("SELECT system_id,flow_id,form_id,form_key,flow_code,flow_code_seq,back_code + FROM flow where form_key ='$formKey'"); + // echo " FLow 33:" . "SELECT system_id,flow_id,form_id,form_key,flow_code,flow_code_seq,back_code + // FROM flow where form_key ='$formKey'"; + } + } + + public function getParentKey() + { + list($parent_key) = DB::fields("select parent_key from workflow_subflow + where form_key='" . $this->form_key . "' "); + return $parent_key; + } + public static function getParentFormKey($formKey) + { + list($parent_key) = DB::fields("select parent_key from workflow_subflow + where form_key='" . $formKey . "' "); + return $parent_key; + } + public static function getSplitFlowCode() + { + } + + /** + * @param $formKey + * @param $flowCode + */ + static function updateFlowCode($formKey, $flowCode) + { + $where = "form_key = '" . $formKey . "'"; + DB::update_table("flow", array( + "flow_code" => $flowCode + ), $where); + } + /** + * 生成新的formkey + * @return string + */ + public static function getNewFormKey() + { + // list($curvalformKey) = DB::fields("SELECT appwms.currval('form_key') form_key"); + // echo " curvalformKey line69 :" . $curvalformKey."
"; + list($formKey) = DB::fields("SELECT appwms.nextval('form_key') form_key"); + // echo " formKey line77:" . $formKey."
"; + return $formKey; + } + + public function insert() + { + DB::insert_table("flow", array( + "form_key" => $this->form_key, + "system_id" => $this->system_id, + "flow_id" => $this->flow_id, + "form_id" => $this->form_id, + "flow_code" => $this->flow_code, + "flow_code_seq" => $this->flow_code_seq, + "back_code" => $this->back_code + )); + } + public function save() + { + list($cnt) = DB::fields("select count(*) from flow where form_key='" . $this->form_key . "' "); + + if ($cnt == 0) { + // echo "CNT : ".$cnt; + DB::insert_table("flow", array( + "form_key" => $this->form_key, + "system_id" => $this->system_id, + "flow_id" => $this->flow_id, + "form_id" => $this->form_id, + "flow_code" => $this->flow_code, + "flow_code_seq" => $this->flow_code_seq, + "back_code" => $this->back_code + )); + } else { + $where = "form_key = '" . $this->form_key . "'"; + DB::update_table("flow", array( + "flow_code" => $this->flow_code , + "flow_code_seq" => $this->flow_code_seq , + "back_code" => $this->back_code + ), $where); + } + } + + /** + * @return string + */ + public function getFormKey() + { + return $this->form_key; + } + + /** + * @return mixed + */ + public function getFormId() + { + return $this->form_id; + } + /** + * @return mixed + */ + public function getFlowId() + { + return $this->flow_id; + } + + + /** + * @return mixed + */ + public function getSystemId() + { + return $this->system_id; + } + + /** + * @param mixed $system_id + * @return Flow + */ + public function setSystemId($system_id) + { + $this->system_id = $system_id; + return $this; + } + + /** + * @param mixed $flow_id + * @return Flow + */ + public function setFormId($form_id) + { + $this->form_id = $form_id; + return $this; + } + + /** + * @param mixed $flow_code + * @return Flow + */ + public function setFlowCode($flow_code) + { + $this->flow_code = $flow_code; + return $this; + } + /** + * @return mixed + */ + public function setFlowId($flow_id) + { + $this->flow_id = $flow_id; + return $this; + } + /** + * @return mixed + */ + public function getFlowCode() + { + return $this->flow_code; + } +} diff --git a/workflow/model/NodeTask.php b/workflow/model/NodeTask.php new file mode 100644 index 00000000..d3356d49 --- /dev/null +++ b/workflow/model/NodeTask.php @@ -0,0 +1,426 @@ + "CounterSignSubtaskHandler", + self::NEXT_ASSIGNER_MODIFY_TASK => "NextAssignerModifyTaskHandler", + self::FH_TASK => "FhTaskHandler", + self::B4_TASK => "B4TaskHandler", + self::B7_TASK => "B7TaskHandler" + ); + + public function update() + { + $where = "task_id = '" . $this->task_id . "'"; + DB::update_table("workflow_task", array( + "form_key" => $this->getFormKey(), + "flow_code" => $this->getFlowCode(), + "task_type" => $this->getTaskType(), + "completion_condition" => $this->getCompletionCondition(), + "state" => $this->getState(), + "join_role" => $this->getJoinRole(), + "role_type" => $this->getRoleType(), + "necessary" => $this->getNecessary(), + "creator" => $this->getCreator(), + "error_info" => $this->getErrorInfo(), + "create_code" => $this->getCreateCode(), + "wf_condition" => $this->getWfCondition(), + "remark" => $this->getRemark() + ), $where); + } + + public function delete() + { + DB::query("delete from workflow_task where task_id='" . $this->task_id . "' ", $db = 'default'); + } + + function parseRole() + { + $function = "_roleIs" . $this->getRoleType(); + if (!method_exists('NodeTask', $function)) { + return self::processUndefined($function); + } + return $this->$function(); + } + + /** + * @return mixed + */ + public function getCreator() + { + return $this->creator; + } + + /** + * @param mixed $creator + * @return NodeTask + */ + public function setCreator($creator) + { + $this->creator = $creator; + return $this; + } + + /** + * @return mixed + */ + public function getCreateCode() + { + return $this->create_code; + } + + /** + * @param mixed $create_code + * @return NodeTask + */ + public function setCreateCode($create_code) + { + $this->create_code = $create_code; + return $this; + } + + /** + * @return mixed + */ + public function getWfCondition() + { + return $this->wf_condition; + } + + /** + * @param mixed $condition + * @return NodeTask + */ + public function setWfCondition($condition) + { + $this->wf_condition = $condition; + return $this; + } + + private function _roleIsString() + { + #以下为专人 + $strAssign = $this->getJoinRole(); + $assignEmps = array(); + $arr_a = explode('|', $strAssign); + foreach ($arr_a as $key => $value) { + if (empty($value)) { + continue; + } + $arr_b = explode(':', $value); + $val = explode('-', $arr_b[0]); + $arr_c = explode(',', $arr_b[1]); + $str_next_user = ""; + foreach ($arr_c as $key => $value) { + if (empty($value)) { + continue; + } + if ($value == '00000') { + $str_next_user .= '00000' . '-' . "00000,"; + } else { + $str_next_user .= AssignerStringParser::process($value); + } + } + array_push($assignEmps, array( + 'assign_status' => $val[0], //assign_status + 'assigner_string' => $str_next_user + )); + } + return $assignEmps; + } + + private function _roleIsSQL() + { + return DB::result($this->getJoinRole()); + } + + /** + * @return mixed + */ + public function getTaskId() + { + return $this->task_id; + } + + /** + * @param mixed $task_id + * @return NodeTask + */ + public function setTaskId($task_id) + { + $this->task_id = $task_id; + return $this; + } + + /** + * @return mixed + */ + public function getTaskType() + { + return $this->task_type; + } + + /** + * @param mixed $task_type + * @return NodeTask + */ + public function setTaskType($task_type) + { + $this->task_type = $task_type; + return $this; + } + + /** + * @return mixed + */ + public function getFlowCode() + { + return $this->flow_code; + } + + /** + * @param mixed $flow_code + * @return NodeTask + */ + public function setFlowCode($flow_code) + { + $this->flow_code = $flow_code; + return $this; + } + + /** + * @return mixed + */ + public function getFormKey() + { + return $this->form_key; + } + + /** + * @param mixed $form_key + * @return NodeTask + */ + public function setFormKey($form_key) + { + $this->form_key = $form_key; + return $this; + } + + /** + * @return mixed + */ + public function getNecessary() + { + return $this->necessary; + } + + /** + * @param mixed $necessary + * @return NodeTask + */ + public function setNecessary($necessary) + { + $this->necessary = $necessary; + return $this; + } + + /** + * @return mixed + */ + public function getCompletionCondition() + { + return $this->completion_condition; + } + + /** + * @param mixed $completion_condition + * @return NodeTask + */ + public function setCompletionCondition($completion_condition) + { + $this->completion_condition = $completion_condition; + return $this; + } + + /** + * @return mixed + */ + public function getState() + { + return $this->state; + } + + /** + * @param mixed $state + * @return NodeTask + */ + public function setState($state) + { + $this->state = $state; + return $this; + } + + /** + * @return mixed + */ + public function getJoinRole() + { + return $this->join_role; + } + + /** + * @param mixed $join_role + * @return NodeTask + */ + public function setJoinRole($join_role) + { + $this->join_role = $join_role; + return $this; + } + + /** + * @return mixed + */ + public function getErrorInfo() + { + return $this->error_info; + } + + /** + * @param mixed $error_info + * @return NodeTask + */ + public function setErrorInfo($error_info) + { + $this->error_info = $error_info; + return $this; + } + + /** + * @return mixed + */ + public function getRemark() + { + return $this->remark; + } + + /** + * @param mixed $remark + * @return NodeTask + */ + public function setRemark($remark) + { + $this->remark = $remark; + return $this; + } + + /** + * @return mixed + */ + public function getCreateDate() + { + return $this->create_date; + } + + /** + * @param mixed $create_date + * @return NodeTask + */ + public function setCreateDate($create_date) + { + $this->create_date = $create_date; + return $this; + } + + /** + * @return mixed + */ + public function getFinishDate() + { + return $this->finish_date; + } + + /** + * @param mixed $finish_date + * @return NodeTask + */ + public function setFinishDate($finish_date) + { + $this->finish_date = $finish_date; + return $this; + } + + /** + * @return mixed + */ + public function getPhase() + { + return $this->phase; + } + + /** + * @param mixed $phase + * @return NodeTask + */ + public function setPhase($phase) + { + $this->phase = $phase; + return $this; + } + + /** + * @return mixed + */ + public function getRoleType() + { + return $this->role_type; + } + + /** + * @param mixed $role_type + * @return NodeTask + */ + public function setRoleType($role_type) + { + $this->role_type = $role_type; + return $this; + } +} diff --git a/workflow/model/Subflow.php b/workflow/model/Subflow.php new file mode 100644 index 00000000..5a6e8f72 --- /dev/null +++ b/workflow/model/Subflow.php @@ -0,0 +1,150 @@ +getFormKey() == null) { + $this->form_key = Flow::getNewFormKey(); + } else { + $this->form_key = $flow->getFormKey(); + } + } + + function getFormKey() + { + return $this->form_key; + } + + public static function delete($formKey = null) + { + DB::query("DELETE subflow WHERE Form_Key = '" . $formKey . "'"); + } + + /** + * @param $userId + * @return $this + */ + public function setCurrentUser($userId) + { + $this->current_assigner = $userId; + return $this; + } + + /** + *变更当前签核人员 + * @param $formKey + * @param $userId + */ + public static function updateCurrentUser($formKey, $userId) + { + $where = "form_key = '" . $formKey . "'";; + DB::update_table("subflow", array( + "current_assigner" => $userId, + ), $where); + + } + + /** + * 获取当前签核者 + * @param $formKey + * @return userId + */ + public static function getCurrentUser($formKey) + { + list($currentAssigner) = DB::fields("SELECT current_assigner + FROM subflow where form_key ='$formKey'"); + + return $currentAssigner; + } + + /*** + * + *关闭签核 + * @param null $formKey + */ + public static function close($formKey = null) + { + $where = "form_key = '" . $formKey . "'";; + DB::update_table("subflow", array( + "current_assigner" => '00000' + ), $where); + } + + /** + * + * @param null $formKey + */ + public static function suspend($formKey = null) + { + + self::updateRealId($formKey, self::getCurrentUser($formKey)); + $where = "form_key = '" . $formKey . "'"; + DB::update_table("subflow", array( + "current_assigner" => self::SUSPEND_STATE, + + ), $where); + } + + /** + * + * @param $formKey + * @param $userId + */ + public static function updateRealId($formKey, $userId) + { + $where = "form_key = '" . $formKey . "'";; + DB::update_table("subflow", array( + "real_id" => $userId, + ), $where); + } + + /** + * + * @param $formKey + * @param $userId + * @return + */ + public static function getRealId($formKey) + { + list($real_id) = DB::fields("SELECT real_id + FROM subflow where form_key ='$formKey'"); + return $real_id; + + } + + /** + * 插入记录 + * @return int + */ + public function insert() + { + list($cnt) = DB::fields("select count(*) from subflow where from_key='" . $this->form_key . "' "); + if ($cnt == 0) { + DB::insert_table("subflow", array( + "form_key" => $this->form_key, + "seq" => $this->seq + 1, + "current_assigner" => $this->current_assigner, + "real_id" => $this->real_id + )); + return 1; + } + return -1; + + } + + public function __toString() + { + return json_encode($this); + } +} + diff --git a/workflow/model/SubflowManager.php b/workflow/model/SubflowManager.php new file mode 100644 index 00000000..619ce9d5 --- /dev/null +++ b/workflow/model/SubflowManager.php @@ -0,0 +1,242 @@ +parent_key = $parentFlow->getFormKey(); + } + $this->seq = $this->_getSeq(); + } + + public function __toString() + { + return json_encode($this); + } + + public static function getDetail($parentKey, $seq = 0) + { + $detail = DB::result("select * from workflow_subflow where + seq='" . $seq . "' and parent_key ='" . $parentKey . "'"); + return $detail; + + } + + /** + * @desc workflow_sublow 新增一条记录 + * @param Subflow $subflow + * @param $sender + * @param int $seq + */ + public function append(Subflow $subflow, $sender, $seq = null) + { + DB::query("insert into workflow_subflow (FORM_KEY, SEQ, PARENT_KEY, LEADER_NO, CREATE_DATE, SENDER) + values ('" . $subflow->getFormKey() . "', + '" . $this->seq . "', + '" . $this->parent_key . "', + '" . $subflow->current_assigner . "', + now(), + '" . $sender . "' ) "); + + } + + static function getChildNode($childFormKey) + { + + + $node = DB::result("select * from workflow_subflow where form_key + ='" . $childFormKey . "'"); + return $node[0]; + } + + /** + * 未回复统计 + * @return integer|null + */ + public function getUnReplyCount($seq = null) + { + if ($seq == null) { + return null; + } + list($cnt) = DB::fields("select count(*) from workflow_subflow where + reply_flag is null and seq='" . $seq . "' and parent_key ='" . $this->parent_key . "'"); + return $cnt; + } + + /** + * 未回复明细 + * @return array|void + */ + public function getUnReplyDetail($seq = null) + { + if ($seq == null) { + return null; + } + list($detail) = DB::fields("select * from workflow_subflow where + reply_flag is null and seq='" . $seq . "' and parent_key ='" . $this->parent_key . "'"); + return $detail; + } + + /** + * 已回复统计 + * @param null $seq + * @return integer + */ + public function getReplyCount($seq = null) + { + if ($seq == null) { + return null; + } + list($cnt) = DB::fields("select count(*) from workflow_subflow where + reply_flag is not null and seq='" . $seq . "' and parent_key ='" . $this->parent_key . "'"); + return $cnt; + } + + /** + * 已回复明细 + * @param null $seq 会签的序号 + * @return integer + */ + public function getReplyDetail($seq = null) + { + if ($seq == null) { + return null; + } + $detail = DB::result("select * from workflow_subflow where + reply_flag is not null and seq='" . $seq . "' and parent_key ='" . $this->parent_key . "'"); + return $detail; + } + + /** + * 获取$parentKey 已经会签或拆分的次数 + * @return integer + */ + private function _getSeq() + { + list($cnt) = DB::fields("select nvl(max(seq),-1)+1 from workflow_subflow where + parent_key ='" . $this->parent_key . "'"); + return $cnt; + } + + /** + * 获取$parentKey已经会签或拆分的次数 + * @return integer + */ + public static function getSeqByFormKey($formKey) + { + list($seq) = DB::fields("select seq from workflow_subflow where + form_key ='" . $formKey . "'"); + return $seq; + } + + /** + * 获取该节点 + * @param $formKey + * @return integer + */ + public static function getCurrentParentFlowCode($formKey) + { + $flow = new Flow($formKey); + list($flow_code) = DB::fields("select flow_code from flow where + form_key ='" . $flow->getParentKey() . "'"); + return $flow_code; + } + + /** + * @param $formKey + * @param $flag REPLY_FLAG + */ + public static function updateReplyFlag($formKey, $flag) + { + $where = "form_key = '" . $formKey . "'"; + DB::update_table("workflow_subflow", array( + "REPLY_FLAG" => "'" . $flag . "'" + ), $where); + + } + + /** + * + * 获取会签中不同意的数量 + * @param $seq + * @return null + */ + public function getRejectOpinionCount($seq) + { + if ($seq == null) { + return null; + } + $details = $this->getReplyDetail($seq); + $cnt = 0; + foreach ($details as $row) { + if ($row['reply_flag'] == 'N') { + $cnt++; + } + } + return $cnt; + + } + + /** + * + * 获取会签中不同意的数量 + */ + public function getAcceptOpinionCount($seq) + { + if ($seq == null) { + return null; + } + $details = $this->getReplyDetail($seq); + $cnt = 0; + foreach ($details as $row) { + if ($row['reply_flag'] == 'Y') { + $cnt++; + } + } + return $cnt; + + } + + public static function updateReplyComment($formKey, $comment) + { + $where = "form_key = '" . $formKey . "'"; + DB::update_table("workflow_subflow", array( + "REPLY_COMMENT" => "'" . $comment . "'" + ), $where); + self::updateChangeDate($formKey); + } + + public static function getReplyComment($formKey) + { + + $detail = DB::result("select reply_comment from workflow_subflow where + form_key='" . $formKey . "'"); + return $detail; + } + + public static function getCounterSignComments($parentKey) + { + $sql = "select rownum seq ,seq CS_SEQ ,LEADER_NO ASSIGNER,reply_comment ASSIGN_OPINION ,change_date ASSIGN_DATE , LEAD_CODE, + f_return_content('lead_code',LEAD_CODE) POSITION_NAME,case Reply_flag when 'Y' then 'F1' + when 'N' then 'Y1' else 'A4' end ASSIGN_STATUS,'' FLOW_CODE from workflow_subflow a,employee b + where parent_key='" . $parentKey . "' and a.leader_no=b.employee_no"; + return DB::result($sql); + } + + public static function updateChangeDate($formKey) + { + $sql = "update workflow_subflow set change_date=sysdate where form_key='" . $formKey . "'"; + DB::query($sql); + } + +} \ No newline at end of file diff --git a/workflow/model/TaskManager.php b/workflow/model/TaskManager.php new file mode 100644 index 00000000..afd715a1 --- /dev/null +++ b/workflow/model/TaskManager.php @@ -0,0 +1,122 @@ +setTaskId($row['task_id']) + ->setFormKey($row['form_key']) + ->setNecessary($row['necessary']) + ->setTaskType($row['task_type']) + ->setErrorInfo($row['error_info']) + ->setRemark($row['remark']) + ->setFlowCode($row['flow_code']) + ->setCompletionCondition($row['completion_condition']) + ->setState($row['state']) + ->setCreator($row['creator']) + ->setJoinRole($row['join_role']) + ->setRoleType($row['role_type']) + ->setTaskType($row['task_type']) + ->setWfCondition($row['wf_condition']) + ->setCreateCode($row['create_code']); + + array_push($tasks, $task); + } + return $tasks; + } + + public static function getTasks(NodeTask $task) + { + $taskClass = new ReflectionClass('NodeTask'); + $props = $taskClass->getProperties(); + + $condition = array(); + $sql = "select * From workflow_task where 1=1 "; + foreach ($props as $prop) { + $val = $prop->getValue($task); + $name = $prop->getName(); + if (is_null($val) || empty($val) || $prop->isStatic()) continue; + $condition[$name] = $val; + $sql .= " and $name = '$val' "; + } + $tasks = array(); + //return $tasks; + $result = DB::result($sql, true); + $tasks = array(); + // var_dump( $result); + foreach ($result as $row) { + $task = new NodeTask(); + $task->setTaskId($row['task_id']) + ->setFormKey($row['form_key']) + ->setNecessary($row['necessary']) + ->setTaskType($row['task_type']) + ->setErrorInfo($row['error_info']) + ->setRemark($row['remark']) + ->setFlowCode($row['flow_code']) + ->setCompletionCondition($row['completion_condition']) + ->setState($row['state']) + ->setJoinRole($row['join_role']) + ->setCreator($row['creator']) + ->setRoleType($row['role_type']) + ->setWfCondition($row['wf_condition']) + ->setTaskType($row['task_type']) + ->setCreateCode($row['create_code']); + array_push($tasks, $task); + } + return $tasks; + } + + static function closeTaskByFormKey($formKey, $flowCode = "") + { + return null; + } + + public static function insertTask(NodeTask $task) + { + $task_id = self::getNewTaskId(); + //var_dump( $task_id); + DB::insert_table("workflow_task", array( + "task_id" => $task_id, + "form_key" => $task->getFormKey(), + "flow_code" => $task->getFlowCode(), + "task_type" => $task->getTaskType(), + "completion_condition" => $task->getCompletionCondition(), + "state" => $task->getState(), + "necessary" => $task->getNecessary(), + "error_info" => $task->getErrorInfo(), + "join_role" => $task->getJoinRole(), + "creator" => $task->getCreator(), + "role_type" => $task->getRoleType(), + "remark" => $task->getRemark(), + "phase" => $task->getPhase(), + "wf_condition" => $task->getWfCondition(), + 'create_code' => $task->getCreateCode(), + )); + return $task_id; + } + + static function getNewTaskId() + { + list($msec, $sec) = explode(' ', microtime()); + return date('YmdHis') . str_pad((sprintf("%0.4f", $msec) * 10000), 4, STR_PAD_LEFT); + } +} diff --git a/workflow/model/WorkFLowItems.php b/workflow/model/WorkFLowItems.php new file mode 100644 index 00000000..c7b942eb --- /dev/null +++ b/workflow/model/WorkFLowItems.php @@ -0,0 +1,240 @@ +setSystemId($systemId) + ->setFlowId($flowId); + } + + /** + * @param string $systemId + * @param string $flowId + * @return array|void + */ + public static function get_records($systemId = "", $flowId = "") + { + // var_dump($_SERVER['DOCUMENT_ROOT']); + + $where = " "; + $where .= !empty($systemId) ? (" and system_id like '" . $systemId . "%'") : ""; + $where .= !empty($flowId) ? (" and flow_id like '" . $flowId . "%'") : ""; + $where = $where == "where " ? "" : $where; + + return DB::result("SELECT system_id,flow_id,creator,create_date, + wf_file,wf_layout,wf_version,wf_name + FROM workflow_items where 1=1 " . $where, false); + } + + public function save() + { + + #这里针对主机 + $directory = self::PREFIX_SAVE_DIR . $this->getSystemId(); + if (!file_exists($directory)) { + mkdir($directory, 0777, true); + chmod($directory, 0777); + } + $this->setWfFile($this->getFlowId() . ".json"); + $path = $directory . "/" . $this->getWfFile(); + echo $path; + DB::query("delete from workflow_items where + system_id='" . $this->getSystemId() . "' and flow_id='" . $this->getFlowId() . "'"); + + DB::insert_table("workflow_items", array( + 'system_id' => $this->getsystemid(), + 'flow_id' => $this->getflowid(), + 'creator' => $this->getcreator(), + 'wf_name' => $this->getwffile(), + 'wf_version' => $this->getwfversion(), + 'wf_layout' => "null", + 'wf_file' => $path + )); + file_put_contents($path, $this->getFlowChart()); + } + + public function parseFcToFields($flowChart = null) + { + + $flowChart = empty($flowChart) ? $this->getFlowChart() : $flowChart; + $_flowChart = json_decode($flowChart, true); + $this->setWfVersion($_flowChart['version'])->setSystemId($_flowChart['systemId']) + ->setFlowChart($flowChart)->setFlowId($_flowChart['flowId'])->setWfName($_flowChart['flowName']); + return $this; + } + + public function setFlowChart($flowChart) + { + $this->flow_chart = $flowChart; + return $this; + } + + /** + * @return mixed + */ + public function getSystemId() + { + return $this->system_id; + } + + /** + * @param mixed $system_id + * @return WorkFLowItems + */ + public function setSystemId($system_id) + { + $this->system_id = $system_id; + return $this; + } + + /** + * @return mixed + */ + public function getFlowId() + { + return $this->flow_id; + } + + /** + * @param mixed $flow_id + * @return WorkFLowItems + */ + public function setFlowId($flow_id) + { + $this->flow_id = $flow_id; + return $this; + } + + /** + * @return mixed + */ + public function getCreator() + { + return $this->creator; + } + + /** + * @param mixed $creator + * @return WorkFLowItems + */ + public function setCreator($creator) + { + $this->creator = $creator; + return $this; + } + + /** + * @return mixed + */ + public function getCreateDate() + { + return $this->create_date; + } + + /** + * @param mixed $create_date + * @return WorkFLowItems + */ + public function setCreateDate($create_date) + { + $this->create_date = $create_date; + return $this; + } + + /** + * @return mixed + */ + public function getWfFile() + { + return $this->wf_file; + } + + /** + * @param mixed $wf_file + * @return WorkFLowItems + */ + public function setWfFile($wf_file) + { + $this->wf_file = $wf_file; + return $this; + } + + /** + * @return mixed + */ + public function getWfLayout() + { + return $this->wf_layout; + } + + /** + * @param mixed $wf_layout + * @return WorkFLowItems + */ + public function setWfLayout($wf_layout) + { + $this->wf_layout = $wf_layout; + return $this; + } + + /** + * @return mixed + */ + public function getWfVersion() + { + return $this->wf_version; + } + + /** + * @param mixed $wf_version + * @return WorkFLowItems + */ + public function setWfVersion($wf_version) + { + $this->wf_version = $wf_version; + return $this; + } + + /** + * @return mixed + */ + public function getWfName() + { + return $this->wf_name; + } + + /** + * @param mixed $wf_name + * @return WorkFLowItems + */ + public function setWfName($wf_name) + { + $this->wf_name = $wf_name; + return $this; + } + + /** + * @return mixed + */ + public function getFlowChart() + { + return $this->flow_chart; + } +}