Browse Source

add workflow

gary
jrbin 2 years ago
parent
commit
730741e5ed
  1. 217
      workflow/FlowContext.php
  2. 38
      workflow/Handler/B4TaskHandler.php
  3. 38
      workflow/Handler/B7TaskHandler.php
  4. 141
      workflow/Handler/CounterSignSubtaskHandler.php
  5. 115
      workflow/Handler/CounterSignTaskHandler.php
  6. 37
      workflow/Handler/EndNodeHandler.php
  7. 31
      workflow/Handler/FhTaskHandler.php
  8. 227
      workflow/Handler/FlowNodeHandler.php
  9. 76
      workflow/Handler/LogicNodeHandler.php
  10. 108
      workflow/Handler/MergeNodeHandler.php
  11. 52
      workflow/Handler/NextAssignerModifyTaskHandler.php
  12. 58
      workflow/Handler/SplitNodeHandler.php
  13. 28
      workflow/Handler/StartNodeHandler.php
  14. 445
      workflow/WorkFlow.php
  15. 464
      workflow/WorkFlowParser.php
  16. 157
      workflow/impl/CommonFlowNode.php
  17. 199
      workflow/impl/CounterSignTask.php
  18. 78
      workflow/impl/EndNode.php
  19. 126
      workflow/impl/FlowNode.php
  20. 125
      workflow/impl/LogicNode.php
  21. 109
      workflow/impl/MailTask.php
  22. 43
      workflow/impl/MergeNode.php
  23. 84
      workflow/impl/Node.php
  24. 54
      workflow/impl/NoticeTask.php
  25. 87
      workflow/impl/SplitNode.php
  26. 128
      workflow/impl/StartNode.php
  27. 8
      workflow/interface/IFlow.php
  28. 5
      workflow/interface/IMerge.php
  29. 8
      workflow/interface/INode.php
  30. 11
      workflow/interface/IRouter.php
  31. 12
      workflow/interface/ISplit.php
  32. 23
      workflow/interface/ITask.php
  33. 29
      workflow/lib/AssignStatus.php
  34. 124
      workflow/lib/AssignerStringParser.php
  35. 209
      workflow/lib/DB.php
  36. 68
      workflow/lib/Depart.php
  37. 171
      workflow/lib/Employee.php
  38. 400
      workflow/lib/Logger.php
  39. 41
      workflow/lib/MethodLoader.php
  40. 254
      workflow/model/Assign.php
  41. 17
      workflow/model/Code.php
  42. 191
      workflow/model/Flow.php
  43. 426
      workflow/model/NodeTask.php
  44. 150
      workflow/model/Subflow.php
  45. 242
      workflow/model/SubflowManager.php
  46. 122
      workflow/model/TaskManager.php
  47. 240
      workflow/model/WorkFLowItems.php

217
workflow/FlowContext.php

@ -0,0 +1,217 @@
<?php
/**
* @property mixed|null currentNode
*/
class FlowContext
{
public $systemId;
public $flowId;
public $formId;
public $currentAssigner;
public $currentNode;
public $flowCode;
public $nextAssigner;
public $assignStatus;
public $assignOpinion;
public $formKey;
public $workFlowParser;
/**
* @return mixed|null
*/
public function getCurrentNode()
{
return $this->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;
}
}

38
workflow/Handler/B4TaskHandler.php

@ -0,0 +1,38 @@
<?php
/**
* User: u73376
* Date: 2018/10/16
* Time: 16:48
*/
class B4TaskHandler
{
function doWork()
{
return;
}
/**
* @param $assigners
* @param NodeTask $task
* @return mixed
*/
public function setNextAssignerList($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;
}
}

38
workflow/Handler/B7TaskHandler.php

@ -0,0 +1,38 @@
<?php
/**
* User: u73376
* Date: 2018/10/16
* Time: 16:48
*/
class B7TaskHandler
{
function doWork()
{
return;
}
/**
* @param $assigners
* @param NodeTask $task
* @return mixed
*/
public function setNextAssignerList($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;
}
}

141
workflow/Handler/CounterSignSubtaskHandler.php

@ -0,0 +1,141 @@
<?php
/**
* User: user
* Date: 2018/9/10
* Time: 12:03
* @
*/
class CounterSignSubtaskHandler
{
private $formData;
private $flowContext;
private $currentNode;
const DEFAULT_MERGE_OPTION = "AND";
function __construct(FlowContext $flowContext, $formData = array())
{
$this->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);
}
}

115
workflow/Handler/CounterSignTaskHandler.php

@ -0,0 +1,115 @@
<?php
class CounterSignTaskHandler
{
private $currentNode;
private $flowContext;
private $formData;
const DEFAULT_MERGE_OPTION = "AND";
function __construct($node, FlowContext $Context, $formData)
{
$this->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()
{
}
}

37
workflow/Handler/EndNodeHandler.php

@ -0,0 +1,37 @@
<?php
class EndNodeHandler{
private $currentNode;
private $flowContext;
private $formData;
function __construct($node,FlowContext $Context,$formData){
$this->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);
}
}

31
workflow/Handler/FhTaskHandler.php

@ -0,0 +1,31 @@
<?php
/**
* User: u73376
* Date: 2018/10/8
* Time: 14:10
*/
class FhTaskHandler
{
function doWork()
{
return;
}
/**
* @param $assigners
* @param NodeTask $task
* @return mixed
*/
public function setNextAssignerList($assigners, NodeTask $task)
{
$nextAssigners = $task->parseRole();
$newNextAssigners = array();
foreach ($nextAssigners as $row) {
array_push($newNextAssigners, array(0 => $row['assign_status'], 1 => $row['assigner_string']));
}
return $newNextAssigners;
}
}

227
workflow/Handler/FlowNodeHandler.php

@ -0,0 +1,227 @@
<?php
class FlowNodeHandler
{
private $currentNode;
private $flowContext;
private $formData;
function __construct($node, FlowContext $flowContext, $formData)
{
$this->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;
}
}

76
workflow/Handler/LogicNodeHandler.php

@ -0,0 +1,76 @@
<?php
/**
* Created by PhpStorm.
* User: user
* Date: 2018/8/16
* Time: 8:41
*/
class LogicNodeHandler
{
private $currentNode;
private $flowContext;
private $formData;
function __construct($node, FlowContext $Context, $formData)
{
$this->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());
}
}

108
workflow/Handler/MergeNodeHandler.php

@ -0,0 +1,108 @@
<?php
class MergeNodeHandler
{
private $currentNode;
private $flowContext;
const DEFAULT_MERGE_OPTION = "AND";
function __construct($node, $Context)
{
$this->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);
}
}

52
workflow/Handler/NextAssignerModifyTaskHandler.php

@ -0,0 +1,52 @@
<?php
/**
* Created by u73376.
* User: user
* Date: 2018/9/25
* Time: 11:44
*/
class NextAssignerModifyTaskHandler
{
function doWork()
{
return;
}
/**
* @param $assigners
* @param NodeTask $task
* @return mixed
*/
public function setNextAssignerList($assigners, NodeTask $task)
{
$nextAssigners = $task->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;
}*/
}

58
workflow/Handler/SplitNodeHandler.php

@ -0,0 +1,58 @@
<?php
class SplitNodeHandler
{
private $currentNode;
private $flowContext;
function __construct($node, FlowContext $flowContext)
{
$this->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++ . ":<a href='http://localhost/fds/index.php/TestAssign2/show_assign_form/"
. $childFlow->getFormKey() . "' >查看下笔链接</a>" . "<BR/>";
}
}
}
$nextAssigner = $this->flowContext->getNextAssigner();
$currentFlow = new Flow($this->flowContext->getFormKey());
Subflow::updateCurrentUser($currentFlow->getParentKey(), $nextAssigner);
//exit();
/**
*遍历所有下层节点 ,执行对应Handler类doWork方法
*/
}
}

28
workflow/Handler/StartNodeHandler.php

@ -0,0 +1,28 @@
<?php
class StartNodeHandler
{
private $currentNode;
private $flowContext;
function __construct($node, FlowContext $Context)
{
$this->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();
}
}

445
workflow/WorkFlow.php

@ -0,0 +1,445 @@
<?php
class WorkFlow
{
private $formId;
private $systemId;
private $flowId;
private $mainFlow; //主线流程对象
public $currentFlow; //当前流程对象
private $workFlowParser;
public $flowContext;
private $currentAssigner;
private static $logPath = "log/workflow";
private $log;
private $formData;
private $nextAssignList;
private $tester; #测试人员数组
function __construct($systemId, $flowId, $formId, $formKey = null)
{
#实例化日志
$this->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 = "'<option value=00000 >请选择</option>'";
foreach ($nextAssigner as $assigner) {
$htmlOption .= "<option value=" . $assigner[0] . ">"
. Code::getContent('assign_status', $assigner[0]) . "</option>";
}
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;
}
}

464
workflow/WorkFlowParser.php

@ -0,0 +1,464 @@
<?php
error_reporting(E_ALL);
ini_set("display_errors", "on");
class WorkFlowParser
{
private $flowList;
private $flowInfo;
private $traversalMark = array(); //遍历标记private $count=0;
private $count = 0;
private $edgeTo = array();
private $sourceId; //图遍历使用
private $targetId; //图遍历使用
/**
* @param String system_ID
* @param Stirng pFlowId
*/
public function __construct($systemId, $flowId)
{
//加载流程文件
list($wf_file) = DB::fields(" select wf_file from workflow_items
where SYSTEM_ID='$systemId' and FLOW_ID='$flowId'");
// echo $wf_file;
$flowchart = json_decode(file_get_contents($wf_file), true);
//var_dump( file_get_contents("../".$wf_file) );
// var_dump( $flowchart);
$this->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;
}
}

157
workflow/impl/CommonFlowNode.php

@ -0,0 +1,157 @@
<?php
/**
* Created by PhpStorm.
* User: user
* Date: 2019/2/22
* Time: 23:23
*/
require_once 'Node.php';
class CommonFlowNode extends Node
{
private $flow;
private $formData;
function __construct($param)
{
parent::__construct($param);
}
/**
* 获取节点内的FlowCode
* @return mixed
*/
public function getFlowCode()
{
return $this->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;
}
}

199
workflow/impl/CounterSignTask.php

@ -0,0 +1,199 @@
<?php
class CounterSignTask extends Node
{
private $flow;
private $formData;
public function __construct($param)
{
parent::__construct($param);
}
/**
* 指派属性
*/
public function getPropertyAllowAssign()
{
return $this->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;
}
}

78
workflow/impl/EndNode.php

@ -0,0 +1,78 @@
<?php
class EndNode extends CommonFlowNode
{
function __construct($param)
{
parent::__construct($param);
}
public function getBackOption()
{
return null;
}
public function getAssignerList()
{
$strNextUser = "00000-结案,";
$assignerList = array();
array_push($assignerList, array(
"F4", //assign_status
$strNextUser
));
return $assignerList;
}
public function getAssignStatus()
{
//B4-退回:73376,73502,73396|A4-待评估:73376,73502|
$html = "'<option value='00000' >请选择</option>'";
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;
}
}

126
workflow/impl/FlowNode.php

@ -0,0 +1,126 @@
<?php
require_once("CommonFlowNode.php");
class FlowNode extends CommonFlowNode
{
function __construct($param)
{
parent::__construct($param);
}
/**
* 1.首先检查当前节点 assignClass ,如果为专人签核A,则读取下个节点的签核人员,否则根据agentSetting选取上级领导
* @param WorkFlowParser $workFlowParser
* @return array
*/
public function getAssignerList(WorkFlowParser $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;
}
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;
}
}

125
workflow/impl/LogicNode.php

@ -0,0 +1,125 @@
<?php
/**
* Created by u73376.
* User: user
* Date: 2018/8/16
* Time: 8:28
*/
class LogicNode extends CommonFlowNode
{
function __construct($param)
{
parent::__construct($param);
}
public function getRouteMethod()
{
$methodString = $this->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;
}
}

109
workflow/impl/MailTask.php

@ -0,0 +1,109 @@
<?php
class MailTask extends Node
{
/**
* 邮件发送者
*/
public $mailFrom = "";
/**
* 邮件接收者
*/
public $mailTo = "";
/**
* 邮件主题
*/
public $mailSubject = "";
/**
* 邮件内容
*/
public $mailContent = "";
public function __construct($param)
{
$this->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;
}
}

43
workflow/impl/MergeNode.php

@ -0,0 +1,43 @@
<?php
class MergeNode extends Node
{
function __construct($param)
{
parent::__construct($param);
}
/**
* 获取合并选项
* @return mixed
*/
public function getMergeOption()
{
return $this->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;
}
}

84
workflow/impl/Node.php

@ -0,0 +1,84 @@
<?php
class Node
{
const START_NODE = "START_NODE";
const TASK_NODE = "TASK_NODE";
const LOGIC_NODE = "LOGIC_NODE";
const SPLIT_NODE = "SPLIT_NODE";
const MERGE_NODE = "MERGE_NODE";
const FLOW_NODE = "FLOW_NODE";
const END_NODE = "END_NODE";
const COUNTER_SIGN_TASK = "COUNTER_SIGN_TASK";
const COUNTER_SIGN_SUBTASK = "COUNTER_SIGN_SUBTASK";
const ALL_NODE = [
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 $nodeClasses = array(
self::START_NODE=>"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'];
}
}

54
workflow/impl/NoticeTask.php

@ -0,0 +1,54 @@
<?php
class NoticeTask
{
/**
* 邮件发送者
*/
private $noticeList = "";
/**
* 邮件接收者
*/
private $noticeTitle = "";
/**
* 邮件主题
*/
private $noticeUrl = "";
public function __construct($param)
{
// TCP port to connect to
$this->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()
{
}
}

87
workflow/impl/SplitNode.php

@ -0,0 +1,87 @@
<?php
class SplitNode extends Node
{
/**
*返回节点类型
* @param $param
*/
function __construct($param)
{
parent::__construct($param);
}
public function getAssignerList(WorkFlowParser $workFlowParser)
{
$str_next_user = "00000-各部门,";
$assigners = array();
array_push($assigners, array(
"C1", #assign_status
$str_next_user
));
$pathLength = array();
$mergeNodes = $workFlowParser->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;
}
}

128
workflow/impl/StartNode.php

@ -0,0 +1,128 @@
<?php
class StartNode extends CommonFlowNode
{
function __construct($param)
{
parent::__construct($param);
}
/**
* 获取退回选项
* @return mixed|null
*/
public function getBackOption()
{
return empty($this->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 = "'<option value=00000 >请选择</option>'";
$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 .= "<option value=" . $val[0] . ">" . $arr_b[0] . "</option>";
}
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;
}
}

8
workflow/interface/IFlow.php

@ -0,0 +1,8 @@
<?php
interface IFlow extends INode{
/**
* 获取签核人员列表
*/
function getAssignerList();
}

5
workflow/interface/IMerge.php

@ -0,0 +1,5 @@
<?php
interface IMerge extends INode{
function merge();
function getNextFLowCode();
}

8
workflow/interface/INode.php

@ -0,0 +1,8 @@
<?php
interface INode
{
//获取节点的类型
public function getType();
public function getNodeId();
}
?>

11
workflow/interface/IRouter.php

@ -0,0 +1,11 @@
<?php
interface IRouter{
/**
* 合并流程
*/
public function merge();
/**
* 拆分流程
*/
public function split();
}

12
workflow/interface/ISplit.php

@ -0,0 +1,12 @@
<?php
interface ISplit{
/**
* 拆分方法
*/
public function split();
/**
* 获取拆分节点数组
*/
public function getSplitNodes();
}

23
workflow/interface/ITask.php

@ -0,0 +1,23 @@
<?php
interface ITask extends INode{
/**
* 执行任务
*/
public function doTask();
/**
* 设置任务的属性
*/
public function setTaskProperty($objProperty);
/**
* 任务执行之前
*/
public function beforeDoTask();
/**
* 任务执行之后
*/
public function afterDoTask();
}
?>

29
workflow/lib/AssignStatus.php

@ -0,0 +1,29 @@
<?php
/**
* User: u73376
* Date: 2018/8/21
* Time: 23:53
*/
class AssignStatus
{
#不同意的AssignStatus
const REJECT_STATUS = "Y1";
#下一流程节点的AssignStatus
const ACCEPT_STATUS = "F1";
#默认的退回的AssignStaus
const BACK_STATUS = "B1";
#同层流转的AssignStatus
static $same_level_status = array('F6', 'FH');
#退回的AssignStatus
static $back_status = array('B4', 'B7', 'B1');
public static function getContent($statusName = '%')
{
list($value) = DB::fields("select content from code where
field_name ='assign_status' and code_name like '" . $statusName . "%' ");
return $value;
}
}

124
workflow/lib/AssignerStringParser.php

@ -0,0 +1,124 @@
<?php
/**
* User: u73376
* Date: 2018/8/23
* Time: 14:18
*/
class AssignerStringParser
{
/**
* 第一码:数字:员工号;
* 字母D:部门所有员工
* 字母L:部门的领导
* @param $assignerString
* @param string $format
* @param string $delimiter
* @return string 员工号-姓名, 员工号-姓名, 员工号-姓名......
*/
public static function process($assignerString, $format = "employee_no-name position", $delimiter = ",")
{
$_firstCode = substr($assignerString, 0, 1);
if (is_numeric($_firstCode)) {
return self::processCodeN($assignerString, $format, $delimiter);
}
$function = "processCode" . $_firstCode;
if (!method_exists('AssignerStringParser', $function)) {
echo self::processUndefined($function);
exit();
}
return self::$function($assignerString, $format, $delimiter);
}
/**
* 处理第一码为D :获取部门员工
* @param $assignerString
* @param string $format
* @param string $delimiter
* @return string
*/
public static function processCodeD($assignerString, $format = "employee_no-name", $delimiter = ",")
{
$depart = substr($assignerString, 1);
$employees = Depart::getEmployee($depart);
$str_next_user = "";
foreach ($employees as $employee) {
$tmp_str = Employee::get_employee($employee, $format);
$str_next_user .= $tmp_str . $delimiter;
}
return $str_next_user;
}
/**
* 处理第一码为L :获取部门领导
* @param $assignerString
* @param string $format
* @param string $delimiter
* @return string
*/
public static function processCodeL($assignerString, $format = "employee_no-name", $delimiter = ",")
{
$leader = Depart::leader(substr($assignerString, 1));
$tmp_str = Employee::get_employee($leader, $format);
return $tmp_str . $delimiter;
}
/**
*处理第一码为数字 N: 获取 员工号-姓名
* @param $assignerString
* @param string $format
* @param string $delimiter
* @return string
*/
public static function processCodeN($assignerString, $format = "employee_no-name", $delimiter = ",")
{
return Employee::get_employee($assignerString, $format) . $delimiter;
}
/**
*处理第一码为 P: 获取 员工号-姓名
* @param $assignerString
* @param string $format
* @param string $delimiter
* @return string
*/
public static function processCodeP($assignerString, $format = "employee_no-name", $delimiter = ",")
{
return Employee::get_employee($assignerString, $format) . $delimiter;
}
/**
* 处理第一码为E,从节点里的已签核人员选择
* @param $assignerString
* @param string $format
* @param string $delimiter
* @return string
*/
public static function processCodeC($assignerString, $format = "employee_no-name", $delimiter = ",")
{
$flowContext = unserialize($_SESSION['flowContext']);
$code = substr($assignerString, 1);
$records = Assign::get_records($flowContext->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;
}
}

209
workflow/lib/DB.php

@ -0,0 +1,209 @@
<?php
error_reporting(E_ALL);
ini_set("display_errors", "");
class DB
{
private static $ds = array(
'default' => 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;
}
}

68
workflow/lib/Depart.php

@ -0,0 +1,68 @@
<?php
class Depart
{
/**
* 获取部门领导
* @param [type] $dept
* @return void
*/
public static function leader($dept)
{
$_sql="select f_return_depart_leader('".$dept."') LEADER from dual";
list($_leader) = DB::fields($_sql);
return $_leader;
}
public static function depart_name($dept){
$_sql="select max(depart_name) from depart where depart_no='".$dept."'";
list($depart_name) = DB::fields($_sql);
return $depart_name;
}
/**
* 获取所有部门
* @param String,Array $dept
* @return void
*/
public static function get_all_depart($dept)
{
if (is_array($dept)) {
$_sql="select depart_no,depart_name from depart where if_stop is null and (";
foreach ($dept as $val) {
$_or[]= "depart_no like '". $val."%' ";
}
$_sql .= implode('or ', $_or).")";
}
else
{
$_sql="select depart_no,depart_name from depart where if_stop is null and depart_no like '". $dept."%' ";
}
return DB::result($_sql);
}
/**
* 获取部门内部人员
*
* @param String $depart
* @return Array 员工号的数组
*/
public static function getEmployee($depart)
{
if(empty($depart))
return NULL;
$_sql="select employee_no from employee where depart_no like '".$depart."%' ";
$_arr =array();
$result=DB::result($_sql);
foreach ($result as $row) {
if (!empty($row['employee_no'])) {
array_push( $_arr, $row['employee_no']);
}
}
return $_arr;
}
}

171
workflow/lib/Employee.php

@ -0,0 +1,171 @@
<?php
/**
* Class Employee
* Public Property :select 'public $'||lower(COLUMN_NAME)||';' from user_tab_columns
* where table_name='EMPLOYEE'
*/
class Employee
{
public $employee_no;
public $depart_no;
public $name;
public $lead_code;
public $position_code;
public $mail;
public $mail_server;
function __construct($employee_no)
{
list(
$this->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;
}
}

400
workflow/lib/Logger.php

@ -0,0 +1,400 @@
<?php
ini_set('date.timezone', 'Asia/Shanghai');
/**
* Usage:
* $log = new Logger('/var/log/', Logger::INFO);
* $log->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 -->";
}
}
}

41
workflow/lib/MethodLoader.php

@ -0,0 +1,41 @@
<?php
/**
* User: u73376
* Date: 2018/8/17
* Time: 9:37
*/
class MethodLoader
{
#临时类文件存放目录
/**
* @param $methodString 可以转为方法的字符串
* @return object
*/
static function getInstanceByMethodString($methodString)
{
$obj = new class($methodString)
{
private $methodString;
public function __construct($methodString)
{
$this->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;
}
}

254
workflow/model/Assign.php

@ -0,0 +1,254 @@
<?php
class Assign
{
public $form_key;
public $seq;
public $assigner;
public $assign_status;
public $assign_date;
public $assign_opinion;
public $flow_code;
public $flow_code_seq;
public $real_assigner;
/**
* @return null
*/
public function getFormKey()
{
return $this->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
));
}
}

17
workflow/model/Code.php

@ -0,0 +1,17 @@
<?php
class Code
{
/**
* @param string $fieldName
* @param string $codeName
* @return mixed
*/
public static function getContent($fieldName = '%', $codeName = '%')
{
list($value) = DB::fields("select content from code where
field_name like '" . $fieldName . "%' and code_name like '" . $codeName . "%' ");
return $value;
}
}

191
workflow/model/Flow.php

@ -0,0 +1,191 @@
<?php
class Flow
{
public $system_id;
public $form_id;
public $flow_id;
public $form_key;
public $flow_code;
public $flow_code_seq = 0;
public $back_code;
/**
* @param null $formKey
*/
public function __construct($formKey = null)
{
if ($formKey == null or empty($formKey)) {
$this->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."<Br/>";
list($formKey) = DB::fields("SELECT appwms.nextval('form_key') form_key");
// echo " formKey line77:" . $formKey."<Br/>";
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;
}
}

426
workflow/model/NodeTask.php

@ -0,0 +1,426 @@
<?php
/**
* User: u73376
* Date: 2018/9/8
* Time: 19:27
*/
class NodeTask
{
/* select 'public $'||lower(COLUMN_NAME)||';' from user_tab_columns
where table_name='WORKFLOW_TASK' */
public $task_id;
public $task_type;
public $flow_code;
public $form_key;
public $necessary;
public $completion_condition;
public $state;
public $join_role;
public $error_info;
public $remark;
public $create_date;
public $finish_date;
public $role_type;
public $wf_condition;
public $creator;
public $create_code;
public $phase;
const TASK_CLOSE_STATE = "CLOSE";
const TASK_OPEN_STATE = "OPEN";
const TASK_FINISH_STATE = "FINISH";
const ALL_TASK = "10000000";
const COUNTER_SIGN_SUBTASK = "01000000";
const NEXT_ASSIGNER_MODIFY_TASK = "00100000";
const FH_TASK = "00010000";
const B4_TASK = "00001000";
const B7_TASK = "00000100";
static $handlerClasses = array(
self::COUNTER_SIGN_SUBTASK => "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;
}
}

150
workflow/model/Subflow.php

@ -0,0 +1,150 @@
<?php
class Subflow
{
private $form_key;
private $seq = 0;
public $current_assigner;
private $real_id;
private $receive_date;
private $pre_finish_date;
#会签 状态 S0001
const SUSPEND_STATE = "S0001";
public function __construct(Flow $flow)
{
if ($flow->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);
}
}

242
workflow/model/SubflowManager.php

@ -0,0 +1,242 @@
<?php
/***
* Class SubflowManager
* @desc 对workflow_sublow 新增查询操作
* @date 2018年8月5日11:42:58
* @author u73376@yuntay.com.cn
*/
class SubflowManager
{
private $parent_key;
private $seq = 0;
public function __construct(Flow $parentFlow = null)
{
if (!empty($parentFlow)) {
$this->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);
}
}

122
workflow/model/TaskManager.php

@ -0,0 +1,122 @@
<?php
/**
* User: u73376
* Date: 2018/9/8
* Time: 18:04
*/
class TaskManager
{
/**
* @param $formKey
* @param string $flowCode
* @param string $state
* @return array|void
*/
public static function getTask($formKey, $flowCode = "%", $taskType = "%", $state = "OPEN")
{
$result = DB::result("select * from workflow_task
where form_key='" . $formKey . "' and state='" . $state . "'
and flow_code like '" . $flowCode . "%'
and task_type like '" . $taskType . "%'");
$tasks = array();
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'])
->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);
}
}

240
workflow/model/WorkFLowItems.php

@ -0,0 +1,240 @@
<?php
error_reporting(E_ALL);
ini_set("display_errors", "on");
define('BASE_PATH',str_replace('//','/',realpath(dirname(__FILE__).'/'))."/");
class WorkFLowItems
{
public $system_id;
public $flow_id;
public $creator;
public $create_date;
public $wf_file;
public $wf_layout;
public $wf_version;
public $wf_name;
public $flow_chart;
const PREFIX_SAVE_DIR =BASE_PATH. "../../static/flow/";
public function __construct($systemId = null, $flowId = null)
{
$this->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;
}
}
Loading…
Cancel
Save