/** * 转发图度 * */ public function sendAction() { $post = $this->_request->getPost(); $post = array_merge(array('to' => '', 'cc' => ''), $post); $action = $post['action']; $type = $post['type']; // 判断操作,默认为发送 if (!in_array($action, array('send', 'save'))) { $action = 'send'; } // 判断类型,默认为任务 if (!in_array($type, array('task', 'discuss', 'notice'))) { $type = 'task'; } // 当前用户唯一ID $uniqueId = $this->_user['uniqueid']; // 是否现在发送 $isSend = true; // 是否已经发送过,可判读来源的图度是否发送过,已发送过的不允许保存为草稿 $isSent = false; // 是否转发 $isForward = !empty($post['forward']); // 是否来源于草稿 $isFromDraft = false; // 是否发起人 $isSender = false; // 是否执行人 $isAccpter = false; // 是否通知所有关联人员 $notifyAll = !empty($post['notifyall']); // 需要发送提醒的人 $notifyTo = array(); // 抄送人加入自己 $post['cc'] .= "\n" . $this->_user['email'] . ' ' . $this->_user['truename']; // 需要发送的地址,可能为空 $address = array('to' => $this->_formatRecipients($post['to']), 'cc' => $this->_formatRecipients($post['cc'], true)); // 需要发送的执行人,方便后面调用 $accepters = $address['to']; // 需要投递的联系人数据,保存用户唯一ID // uniqueid => array(isaccepter => {boolean}, accepterinfo => {string}) $recipients = array(); // 需要移除接受人的用户唯一ID $removeAccepters = array(); if (null === $this->_tudu) { return $this->json(false, $this->lang['tudu_not_exists']); } $fromTudu = $this->_tudu; // 日志记录内容 $tuduLog = array('action' => 'create', 'detail' => array()); $postLog = array('action' => 'create', 'detail' => array()); //////////////////////////// // 操作及参数判断 // 发送操作 if ('send' == $action) { $isAccpter = array_key_exists($this->_user['email'], $accepters); // 如果是转发 if ($isForward) { // 转发时,必须有图度存在 if (!$fromTudu) { $this->json(false, $this->lang['tudu_not_exists']); } // 图度组不能转发 if ($fromTudu->isTuduGroup) { $this->json(false, $this->lang['deny_forward_tudugroup']); } // 非图度执行人不能转发图度 if (!in_array($this->_user['email'], $fromTudu->accepter)) { $this->json(false, $this->lang['forbid_non_accepter_forward']); } // 执行人不能转发给自己 if ($isAccpter) { $this->json(false, $this->lang['forbid_forward_myself']); } foreach ($address['to'] as $a => $n) { if (in_array($a, $fromTudu->accepter, true)) { $this->json(false, sprintf($this->lang['user_is_accepter'], $n)); } } $tuduLog['action'] = Dao_Td_Log_Log::ACTION_TUDU_FORWARD; } // 保存图度 } else { if ('save' == $action) { $this->json(false); } } // 发送时参数判断,1.检查必须的参数,2.检查联系人是否存在。保存草稿时不需要这些判断 if ($isSend) { if ('task' == $type) { if (empty($address['to']) && (!$fromTudu || !$fromTudu->isTuduGroup)) { $this->json(false, $this->lang['missing_to']); } } else { if (empty($address['cc'])) { $this->json(false, $this->lang['missing_cc']); } } if (!$isForward && empty($post['subject'])) { $this->json(false, $this->lang['missing_subject']); } if (empty($post['content'])) { $this->json(false, $this->lang['missing_content']); } /* @var $daouser Dao_Td_Contact_Contact */ $daoContact = $this->getDao('Dao_Td_Contact_Contact'); /* @var $daoUser Dao_Md_User_User */ $daoUser = Oray_Dao::factory('Dao_Md_User_User'); $forwardInfo = array(); //被转发用户继承转发用户进度 if ($isForward) { $forwardInfo = array('forwardinfo' => $this->_user['truename'] . "\n" . time(), 'percent' => isset($post['percent']) ? (int) $post['percent'] : $fromTudu->selfPercent); } $users = $this->_deliver->getTuduUsers($this->_tudu->tuduId); $isAuth = $fromTudu->isAuth; // 外部联系人转发,仅从当前图度相关用户中检查 foreach ($address['to'] as $a => $name) { foreach ($users as $u) { if ($u['email'] == $a && $u['truename'] == $name) { $unId = $u['uniqueid']; $recipients[$unId] = array_merge(array('uniqueid' => $unId, 'role' => Dao_Td_Tudu_Tudu::ROLE_ACCEPTER, 'accepterinfo' => $a . ' ' . $name, 'percent' => 0, 'tudustatus' => 0, 'isforeign' => $u['isforeign'], 'authcode' => $u['isforeign'] && $isAuth ? Oray_Function::randKeys(4) : null), $forwardInfo); continue 2; } } $unId = Dao_Td_Contact_Contact::getContactId(); $info = Oray_Function::isEmail($a) ? $a . ' ' . $name : $name; $recipients[$unId] = array_merge(array('uniqueid' => $unId, 'role' => Dao_Td_Tudu_Tudu::ROLE_ACCEPTER, 'accepterinfo' => $info, 'percent' => 0, 'tudustatus' => 0, 'isforeign' => 1, 'authcode' => $isAuth ? Oray_Function::randKeys(4) : null), $forwardInfo); } // 去除原有执行人 if ($fromTudu) { $fromAccepter = $this->_deliver->getTuduAccepters($fromTudu->tuduId); $removeInfos = array(); $to = array(); foreach ($fromAccepter as $acpter) { if ($isForward) { if ($acpter['uniqueid'] == $uniqueId) { $removeAccepters[] = $this->_user['uniqueid']; $removeInfos[$this->_user['uniqueid']] = $acpter['accepterinfo']; continue; } } elseif (!isset($recipients[$acpter['uniqueid']]) || !is_array($recipients[$acpter['uniqueid']])) { $removeAccepters[] = $acpter['uniqueid']; $removeInfos[$acpter['uniqueid']] = $acpter['accepterinfo']; continue; } if (isset($recipients[$acpter['uniqueid']]['tudustatus'])) { $recipients[$acpter['uniqueid']]['percent'] = (int) $acpter['percent']; if (!$isForward && $acpter['tudustatus'] != 3) { $recipients[$acpter['uniqueid']]['tudustatus'] = $acpter['tudustatus']; } } $to[] = $acpter['accepterinfo']; $acceptInfo = explode(' ', $acpter['accepterinfo']); $notifyTo[] = $acceptInfo[0]; } $post['to'] = array_unique(array_merge($to, explode("\n", $post['to']))); $post['to'] = implode("\n", $post['to']); if ($fromTudu->isTuduGroup && !empty($removeAccepters)) { /** @var $daoGroup Dao_Td_Tudu_Group */ $daoGroup = $this->getDao('Dao_Td_Tudu_Group'); foreach ($removeAccepters as $unId) { if ($daoGroup->getChildrenCount($fromTudu->tuduId, $unId) > 0) { $this->json(false, sprintf($this->lang['user_has_divide'], $removeInfos[$unId])); } } } } // 处理抄送人 $arrCC = array(); // 外部联系人转发,仅从当前图度相关用户中检查 foreach ($address['cc'] as $a => $name) { foreach ($users as $u) { if ($u['email'] == $a && $u['truename'] == $name) { $unId = $u['uniqueid']; $recipients[$unId] = array('uniqueid' => $unId, 'role' => Dao_Td_Tudu_Tudu::ROLE_CC, 'accepterinfo' => $a . ' ' . $name, 'isforeign' => $u['isforeign'], 'authcode' => $u['isforeign'] && $isAuth ? Oray_Function::randKeys(4) : null); continue 2; } } $unId = Dao_Td_Contact_Contact::getContactId(); $recipients[$unId] = array('uniqueid' => $unId, 'role' => Dao_Td_Tudu_Tudu::ROLE_CC, 'accepterinfo' => $a . ' ' . $name, 'isforeign' => 1, 'authcode' => $isAuth ? Oray_Function::randKeys(4) : null); } // 编辑/转发,合并原有转发人信息 if (null !== $fromTudu) { $fromCC = array(); foreach ($fromTudu->cc as $addr => $cc) { if (!array_key_exists($addr, $address['cc'])) { $fromCC[] = $addr . ' ' . $cc[0]; } } $post['cc'] = implode("\n", $fromCC) . "\n" . $post['cc']; } // 通知所有人 if (in_array($type, array('notice', 'discuss')) || $notifyAll) { $notifyTo = array_merge($notifyTo, $arrCC); } if ($fromTudu) { $users = $this->_deliver->getTuduUsers($fromTudu->tuduId); foreach ($users as $item) { $labels = explode(',', $item['labels']); if (in_array('^t', $labels) && !in_array('^n', $labels)) { $user = $daoUser->getUser(array('uniqueid' => $item['uniqueid'])); $notifyTo[] = $user->address; } } } // 通知跳过当前操作用户(如果有) $notifyTo = array_unique(array_diff($notifyTo, array($this->_user['email']))); if ($type == 'notice' && !isset($post['remind'])) { $notifyTo = null; } //$recipients = array_unique($recipients); //var_dump($address); //var_dump($recipients); } //////////////////////////////// // 参数构造逻辑 // 基本参数 $params = array('orgid' => $this->_tudu->orgId, 'boardid' => $fromTudu ? $fromTudu->boardId : $post['bid'], 'email' => $this->_user['email'], 'type' => $type, 'subject' => isset($post['subject']) ? $post['subject'] : $fromTudu->subject, 'to' => $post['to'], 'cc' => $post['cc'], 'priority' => empty($post['priority']) ? 0 : (int) $post['priority'], 'privacy' => empty($post['privacy']) ? 0 : (int) $post['privacy'], 'status' => Dao_Td_Tudu_Tudu::STATUS_UNSTART, 'lastposttime' => $this->_timestamp, 'content' => $post['content'], 'attachment' => !empty($post['attach']) ? (array) $post['attach'] : array(), 'file' => !empty($post['file']) ? (array) $post['file'] : array()); if (isset($post['starttime'])) { $params['starttime'] = !empty($post['starttime']) ? strtotime($post['starttime']) : null; } if (isset($post['endtime'])) { $params['endtime'] = !empty($post['endtime']) ? strtotime($post['endtime']) : null; } if (isset($post['totaltime']) && is_numeric($post['totaltime'])) { $params['totaltime'] = round((double) $post['totaltime'], 2) * 3600; } if (isset($post['percent'])) { $params['percent'] = min(100, (int) $post['percent']); } if (isset($post['classid'])) { $params['classid'] = $post['classid']; } if (!empty($post['notifyall'])) { $params['notifyall'] = $post['notifyall']; } // 公告置顶 if ($type == 'notice' && !empty($params['endtime']) && $params['endtime'] >= strtotime('today')) { $params['istop'] = 1; } else { $params['istop'] = 0; } // 仅当草稿发送时更新创建时间 if (!$fromTudu || $isFromDraft && $isSend) { $params['createtime'] = $this->_timestamp; } // 更新图度操作时,一些参数设置 if (!isset($params['percent'])) { $params['percent'] = $fromTudu->percent; } if (isset($params['percent'])) { if (100 === $params['percent']) { $params['status'] = Dao_Td_Tudu_Tudu::STATUS_DONE; $params['cycle'] = null; } elseif ($params['percent'] > 0) { $params['status'] = Dao_Td_Tudu_Tudu::STATUS_DOING; } } // 处理日志记录内容 $tuduLog['detail'] = $params; $postLog['detail'] = array('content' => $params['content']); unset($tuduLog['detail']['cycle'], $tuduLog['detail']['vote'], $tuduLog['detail']['email'], $tuduLog['detail']['content'], $tuduLog['detail']['attachment'], $tuduLog['detail']['file'], $tuduLog['detail']['poster'], $tuduLog['detail']['posterinfo']); $logPrivacy = !$isSend; /////////////////////////////////// // 保存图度数据 $tuduId = $fromTudu->tuduId; $postId = $fromTudu->postId; // 内容的参数 $postParams = array('content' => $params['content'], 'lastmodify' => implode(chr(9), array($uniqueId, $this->_timestamp, $this->_user['truename'])), 'createtime' => $this->_timestamp, 'attachment' => $params['attachment'], 'isforeign' => 1, 'file' => !empty($post['file']) ? (array) $post['file'] : array()); // 从未发送时(草稿),相关的数据初始化(时效性的数据清除) if (!$isSent) { // 创建时间可相当于最先发送的时间 $params['createtime'] = $this->_timestamp; // 未发送过,不存在最后编辑 unset($postParams['lastmodify']); } // 不变更发起人 unset($params['from']); if ($isForward) { // 转发,更新最后转发人信息,不更新图度元数据,新建回复内容 unset($postParams['lastmodify']); $params['subject'] = $fromTudu->subject; $params['content'] = $fromTudu->content; $params['status'] = Dao_Td_Tudu_Tudu::STATUS_UNSTART; $params['accepttime'] = null; $params['lastforward'] = implode("\n", array($this->_user['truename'], time())); // 先发送新的回复 $postParams = array_merge($postParams, array('orgid' => $this->_tudu->orgId, 'boardid' => $fromTudu->boardId, 'tuduid' => $tuduId, 'uniqueid' => $this->_user['uniqueid'], 'poster' => $this->_user['truename'], 'email' => $this->_user['email'])); $postId = $this->_deliver->createPost($postParams); if (!$postId) { $this->json(false, $this->lang['save_failure']); } $this->getDao('Dao_Td_Tudu_Post')->sendPost($tuduId, $postId); $postLog['detail'] = $postParams; // 工作流程 $steps = $this->_manager->getSteps($tuduId)->toArray('stepid'); if (!empty($steps) && ($type = 'task')) { $currentStep = $this->_tudu->stepId && false === strpos($this->_tudu->stepId, '^') ? $steps[$this->_tudu->stepId] : array_pop($steps); // 当前为审批步骤 $stepNum = count($steps); $newSteps = array(); $currentTo = array_keys($this->_formatStepRecipients($params['to'])); $fromTo = array_keys($this->_tudu->to); $fromCount = count($fromTo); $isChangeTo = count($currentTo) != $fromCount || count(array_uintersect($fromTo, $currentTo, "strcasecmp")) != $fromCount; if ($isChangeTo) { $prevId = $currentStep['stepid']; $orderNum = $currentStep['ordernum']; $stepId = Dao_Td_Tudu_Step::getStepId(); $newSteps[$stepId] = array('orgid' => $this->_tudu->orgId, 'tuduid' => $tuduId, 'stepid' => $stepId, 'uniqueid' => $uniqueId, 'prevstepid' => $prevId, 'nextstepid' => '^end', 'type' => $this->_tudu->acceptMode ? Dao_Td_Tudu_Step::TYPE_CLAIM : Dao_Td_Tudu_Step::TYPE_EXECUTE, 'ordernum' => ++$orderNum, 'createtime' => time(), 'users' => $this->_formatStepRecipients($params['to'])); $params['stepid'] = $stepId; } // 移除后随未开始执行的步骤 foreach ($steps as $step) { if ($step['ordernum'] > $currentStep['ordernum']) { $this->_manager->deleteStep($tuduId, $step['stepid']); $stepNum--; } } foreach ($newSteps as $step) { if ($this->_manager->createStep($step)) { var_dump($step['users']); $recipients = $this->_prepareStepRecipients($this->_tudu->orgId, $uniqueId, $step['users']); $processIndex = $step['type'] == Dao_Td_Tudu_Step::TYPE_EXAMINE ? 0 : null; $this->_manager->addStepUsers($tuduId, $step['stepid'], $recipients, $processIndex); $stepNum++; } } $params['stepnum'] = $stepNum; } // 更新图度 if (!$this->_deliver->updateTudu($tuduId, $params)) { $this->json(false, $this->lang['save_failure']); } } // 过滤日志变更内容参数 if ($fromTudu) { $arrFromTudu = $fromTudu->toArray(); foreach ($tuduLog['detail'] as $k => $val) { // 记录增加抄送人 if ($k == 'cc') { $arr = explode("\n", $val); foreach ($arr as $idx => $v) { $ccArr = explode(' ', $v); if (array_key_exists($ccArr[0], $fromTudu->cc)) { unset($arr[$idx]); } } if (!$arr) { unset($tuduLog['detail']['cc']); } else { $tuduLog['detail']['cc'] = implode("\n", $arr); } continue; } // 过滤未更新字段 if (array_key_exists($k, $arrFromTudu) && $val == $arrFromTudu[$k]) { unset($tuduLog['detail'][$k]); } } // 内容没有变更 if (!$isForward) { if ($postLog['detail']['content'] == $fromTudu->content) { unset($postLog['detail']); } else { if (isset($postParams['lastmodify'])) { $postLog['detail']['lastmodify'] = $postParams['lastmodify']; } $postLog['detail']['createtime'] = $postParams['createtime']; } } if (empty($tuduLog['detail']['cc'])) { unset($tuduLog['detail']['cc']); } unset($tuduLog['detail']['from']); } // 写入操作日志 $this->_writeLog(Dao_Td_Log_Log::TYPE_TUDU, $tuduId, $tuduLog['action'], $tuduLog['detail'], $logPrivacy); if (!empty($postLog['detail'])) { $this->_writeLog(Dao_Td_Log_Log::TYPE_POST, $postId, $postLog['action'], $postLog['detail'], $logPrivacy); } $sendParams = array(); if ($type != 'task') { $sendParams['notice'] = $type == 'notice'; $sendParams['discuss'] = $type == 'discuss'; } // 删除需要移除的接受人 if ($removeAccepters) { if (!$this->_deliver->removeTuduAccepter($tuduId, $removeAccepters)) { $this->json(false, $this->lang['send_failure']); } } // 发送图度 if (!$this->_deliver->sendTudu($tuduId, $recipients, $sendParams)) { $this->json(false, $this->lang['send_failure']); } // 已发送的任务更新时,设置所有人为未读状态 if ($isSent) { $this->_manager->markAllUnread($tuduId); } // 转发任务时,设置当前关联用户为转发状态 if ($isForward) { $this->_manager->markForward($tuduId, $uniqueId); // 更新转发编辑后的任务进度 $this->_deliver->updateProgress($tuduId, $uniqueId, null); // 更新转发后的任务接受状态 $this->_deliver->updateLastAcceptTime($tuduId, $uniqueId, null); // 移除“我执行”标签 $this->_manager->deleteLabel($tuduId, $uniqueId, '^a'); } // 重新计算父级图度进度 if ($fromTudu && $fromTudu->parentId) { $this->_deliver->calParentsProgress($fromTudu->parentId); } if ('task' == $type) { // 发起人为当前执行人 if ($isAccpter) { // 自动接受任务 $this->_deliver->acceptTudu($tuduId, $uniqueId, null); // 添加我执行 $this->_deliver->addLabel($tuduId, $uniqueId, '^a'); // 接受添加日志 $this->_writeLog(Dao_Td_Log_Log::TYPE_TUDU, $tuduId, Dao_Td_Log_Log::ACTION_TUDU_ACCEPT, array('status' => Dao_Td_Tudu_Tudu::STATUS_DOING, 'accepttime' => time())); // 非当前执行人 } else { // 设为已读 $this->_deliver->markRead($tuduId, $uniqueId); } } $config = $this->_bootstrap->getOption('httpsqs'); // 插入消息队列 $httpsqs = new Oray_Httpsqs($config['host'], $config['port'], $config['chartset'], $config['name']); // 收发规则过滤 $data = implode(' ', array('tudu', 'filter', '', http_build_query(array('tsid' => $this->_tsId, 'tuduid' => $tuduId)))); $httpsqs->put($data, 'tudu'); // 发送外部邮件(如果有),处理联系人 $data = implode(' ', array('send', 'tudu', '', http_build_query(array('tsid' => $this->_tsId, 'tuduid' => $tuduId, 'uniqueid' => $this->_user['uniqueid'], 'to' => '')))); $httpsqs->put($data, 'send'); // IM提醒 if (!empty($notifyTo)) { $content = str_replace('%', '%%', mb_substr(preg_replace('/<[^>]+>/', '', $params['content']), 0, 100, 'UTF-8')); $names = array('task' => '图度', 'discuss' => '讨论', 'notice' => '公告'); $tpl = <<<HTML <strong>您刚收到一个新的{$names[$type]}</strong><br /> <a href="http://{$this->_request->getServer('HTTP_HOST')}/frame#m=view&tid=%s&page=1" target="_blank">%s</a><br /> 发起人:{$this->_user['truename']}<br /> 更新日期:%s<br /> {$content} HTML; $data = implode(' ', array('tudu', 'create', '', http_build_query(array('tuduid' => $this->_tudu->tuduId, 'from' => $this->_user['email'], 'to' => implode(',', $notifyTo), 'content' => sprintf($tpl, $this->_tudu->tuduId, $params['subject'], date('Y-m-d H:i:s', time())))))); $httpsqs->put($data); } $this->json(true, $this->lang['send_success'], $tuduId); }
/** * 认领图度 * * @param string $tuduId */ public function claimTudu($tuduId, $orgId, $uniqueId) { /* @var $daoTudu Dao_Td_Tudu_Tudu */ $daoTudu = $this->getDao('Dao_Td_Tudu_Tudu'); /* @var $daoStep Dao_Td_Tudu_Step */ $daoStep = $this->getDao('Dao_Td_Tudu_Step'); // 获取图度信息 $tudu = $this->getTuduById($tuduId, $uniqueId); if ($tudu->flowId) { return $this->flowClaimTudu($tudu, $orgId, $uniqueId); } // 获取步骤节点信息 $step = $this->getStep($tuduId, $tudu->stepId); $claimAccepter = array(); // 记录认领图度的用户信息 $removeAccepter = array(); // 记录非认领图度的用户信息 $accepters = $daoTudu->getAccepters($tuduId); foreach ($accepters as $accepter) { if ($uniqueId == $accepter['uniqueid']) { $claimAccepter = $accepter; } else { $removeAccepter[] = $accepter; } } // 增加工作流程记录 $stepId = Dao_Td_Tudu_Step::getStepId(); $daoStep->addStep($tuduId, $stepId); $ret = $daoStep->createStep(array('orgid' => $orgId, 'tuduid' => $tuduId, 'uniqueid' => $uniqueId, 'stepid' => $stepId, 'prevstepid' => $tudu->stepId, 'nextstepid' => '^end', 'type' => Dao_Td_Tudu_Step::TYPE_EXECUTE, 'iscurrent' => true, 'isshow' => false, 'ordernum' => $step->orderNum + 1, 'createtime' => time())); if (!$ret) { return false; } $daoStep->addUser(array('tuduid' => $tuduId, 'stepid' => $stepId, 'uniqueid' => $uniqueId, 'userinfo' => $claimAccepter['accepterinfo'], 'processindex' => 1, 'status' => 0)); // 更新图度to字段 $ret = $daoTudu->updateTudu($tuduId, array('to' => $claimAccepter['accepterinfo'], 'stepid' => $stepId, 'stepnum' => $step->orderNum + 1, 'acceptmode' => 0)); if (!$ret) { return false; } $params = array('accepttime' => time(), 'tudustatus' => Dao_Td_Tudu_Tudu::STATUS_DOING); // 更新认领人 td_tudu_user $ret = $daoTudu->updateTuduUser($tuduId, $uniqueId, $params); if (!$ret) { return false; } // 更新图度的接受时间 $daoTudu->updateLastAcceptTime($tuduId); // 更新需要移除的执行人及去除“我执行”标签 if (!empty($removeAccepter)) { foreach ($removeAccepter as $rmAccept) { if (!$daoTudu->updateTuduUser($tuduId, $rmAccept['uniqueid'], array('role' => null))) { continue; } if (!$daoTudu->deleteLabel($tuduId, $rmAccept['uniqueid'], '^a')) { continue; } } } return true; }
/** * 创建图度步骤 * * @param Model_Tudu_Tudu $tudu */ public function createTuduSteps(Model_Tudu_Tudu &$tudu) { /* @var $daoStep Dao_Td_Tudu_Step */ $daoStep = Tudu_Dao_Manager::getDao('Dao_Td_Tudu_Step', Tudu_Dao_Manager::DB_TS); $steps = array(); $currentStepId = null; $orderNum = 1; if ($tudu->reviewer) { $reviewers = $tudu->reviewer; $users = array(); $processIndex = 1; foreach ($reviewers as $item) { foreach ($item as $reviewer) { $users[] = array('email' => $reviewer['email'], 'truename' => $reviewer['truename'], 'processindex' => $processIndex, 'stepstatus' => $processIndex == 1 ? 1 : 0); } $processIndex++; } $stepId = Dao_Td_Tudu_Step::getStepId(); $steps[$stepId] = array('orgid' => $tudu->orgId, 'tuduid' => $tudu->tuduId, 'uniqueid' => $tudu->uniqueId, 'stepid' => $stepId, 'type' => Dao_Td_Tudu_Step::TYPE_EXAMINE, 'prevstepid' => self::NODE_HEAD, 'nextstepid' => self::NODE_END, 'users' => $users, 'ordernum' => $orderNum++, 'createtime' => time()); $currentStepId = $stepId; } if ($tudu->to) { $stepId = Dao_Td_Tudu_Step::getStepId(); $prevId = self::NODE_HEAD; if ($currentStepId) { $steps[$currentStepId]['nextstepid'] = $stepId; $prevId = $currentStepId; } else { $currentStepId = $stepId; } $steps[$stepId] = array('orgid' => $tudu->orgId, 'tuduid' => $tudu->tuduId, 'uniqueid' => $tudu->uniqueId, 'stepid' => $stepId, 'type' => $tudu->acceptMode ? Dao_Td_Tudu_Step::TYPE_CLAIM : Dao_Td_Tudu_Step::TYPE_EXECUTE, 'prevstepid' => $prevId, 'nextstepid' => self::NODE_END, 'users' => $tudu->to, 'ordernum' => $orderNum++, 'createtime' => time()); } foreach ($steps as $step) { if ($this->createStep($step)) { $recipients = $this->_prepareRecipients($tudu->orgId, $tudu->uniqueId, $step['users']); $processIndex = $step['type'] == Dao_Td_Tudu_Step::TYPE_EXAMINE ? 0 : null; $this->_addStepUsers($tudu->tuduId, $step['stepid'], $recipients, $processIndex); } } $tudu->stepId = $currentStepId; $tudu->stepNum = count($steps); }
/** * 认领 * * 必要参数 * tuduid|uniqueid|orgid|username|server|postparams|truename */ public function claim(array $params) { if (empty($params['tuduid'])) { require_once 'Model/Tudu/Exception.php'; throw new Model_Tudu_Exception('Missing or invalid value of parameter "tuduid"', self::CODE_INVALID_TUDUID); } $orgId = $this->_user->orgId; $uniqueId = $this->_user->uniqueId; $userName = $this->_user->userName; $tuduId = $params['tuduid']; //$manager = $this->getManager(); /* @var $daoFlow Dao_Td_Tudu_Flow*/ $daoFlow = Tudu_Dao_Manager::getDao('Dao_Td_Tudu_Flow', Tudu_Dao_Manager::DB_TS); /* @var $daoTudu Dao_Td_Tudu_Flow*/ $daoTudu = Tudu_Dao_Manager::getDao('Dao_Td_Tudu_Tudu', Tudu_Dao_Manager::DB_TS); // 获取图度信息 $tudu = $daoTudu->getTuduById($uniqueId, $tuduId); // 判读图度是否存在 if (null == $tudu) { require_once 'Model/Tudu/Exception.php'; throw new Model_Tudu_Exception('This tudu is not exists', self::CODE_TUDU_NOTEXISTS); } // 获取步骤 $flowRecord = $daoFlow->getFlow(array('tuduid' => $tudu->tuduId)); $step = isset($flowRecord->steps[$flowRecord->currentStepId]) ? $flowRecord->steps[$flowRecord->currentStepId] : null; // 判断当前是否为认领操作 if (!$step || $step['type'] != Dao_Td_Tudu_Step::TYPE_CLAIM) { require_once 'Model/Tudu/Exception.php'; throw new Model_Tudu_Exception('This tudu current step is not claim', self::CODE_STEP_NOTCLAIM); } // 判读图度是否已有user认领 if ($tudu->acceptTime) { require_once 'Model/Tudu/Exception.php'; throw new Model_Tudu_Exception('This tudu current step is claimed', self::CODE_STEP_CLAIM_FINISH); } $accepters = $daoTudu->getAccepters($tuduId); foreach ($accepters as $accepter) { if ($uniqueId == $accepter['uniqueid']) { $claimAccepter = $accepter; } else { $removeAccepter[] = $accepter; } } require_once 'Model/Tudu/Extension/Flow.php'; $flow = new Model_Tudu_Extension_Flow(); $flow->setAttributes($flowRecord->toArray()); // 插入新的步骤 $stepId = Dao_Td_Tudu_Step::getStepId(); $flow->complete($flow->currentStepId, $this->_user->uniqueId); if ($tudu->flowId && strstr($step['next'], 'ST-')) { $flow->deleteStep($step['next']); } $flow->addStep(array('stepid' => $stepId, 'prev' => $step['stepid'], 'next' => $step['next'], 'type' => 0)); $flow->updateStep($step['stepid'], array('next' => $stepId)); $flow->addStepSection($stepId, array(array('uniqueid' => $this->_user->uniqueId, 'truename' => $this->_user->trueName, 'username' => $this->_user->userName, 'email' => $this->_user->userName, 'status' => 0))); $flow->flowTo($stepId); if (!$daoFlow->updateFlow($flow->tuduId, $flow->toArray())) { require_once 'Model/Tudu/Exception.php'; throw new Model_Tudu_Exception('Tudu flow save failed', self::CODE_SAVE_FAILED); } $ret = $daoTudu->updateTudu($tuduId, array('to' => $claimAccepter['accepterinfo'], 'stepid' => $stepId, 'stepnum' => count($flow->steps), 'acceptmode' => 0)); $params = array('accepttime' => time(), 'tudustatus' => Dao_Td_Tudu_Tudu::STATUS_DOING); // 更新认领人 td_tudu_user $ret = $daoTudu->updateTuduUser($tuduId, $uniqueId, $params); if (!$ret) { require_once 'Model/Tudu/Exception.php'; throw new Model_Tudu_Exception('Claim tudu failed', self::CODE_SAVE_FAILED); } // 更新图度的接受时间 $daoTudu->updateLastAcceptTime($tuduId); // 更新需要移除的执行人及去除“我执行”标签 if (!empty($removeAccepter)) { foreach ($removeAccepter as $rmAccept) { if (!$daoTudu->updateTuduUser($tuduId, $rmAccept['uniqueid'], array('role' => null))) { continue; } if (!$daoTudu->deleteLabel($tuduId, $rmAccept['uniqueid'], '^a')) { continue; } } } /* @var $daoPost Dao_Td_Tudu_Post */ $daoPost = Tudu_Dao_Manager::getDao('Dao_Td_Tudu_Post', Tudu_Dao_Manager::DB_TS); $content = sprintf('%s 认领了该图度。', $this->_user->trueName); $header = array('action' => 'claim', 'tudu-claimer' => $this->_user->trueName); $postParams = array('orgid' => $this->_user->orgId, 'boardid' => $tudu->boardId, 'tuduid' => $tudu->tuduId, 'uniqueid' => $this->_user->uniqueId, 'poster' => $this->_user->trueName, 'posterinfo' => $this->_user->position, 'email' => $this->_user->userName, 'postid' => Dao_Td_Tudu_Post::getPostId($tuduId), 'header' => $header, 'content' => $content, 'lastmodify' => implode(chr(9), array($this->_user->uniqueId, time(), $this->_user->trueName))); $postId = $daoPost->createPost($postParams); //发送回复 $daoPost->sendPost($tuduId, $postId); //标记未读 $daoTudu->markAllUnRead($tuduId); // 添加操作日志 $this->_writeLog(Dao_Td_Log_Log::TYPE_TUDU, $tuduId, Dao_Td_Log_Log::ACTION_TUDU_CLAIM, array('orgid' => $orgId, 'uniqueid' => $uniqueId, 'userinfo' => $this->_user->userInfo), array('claimuser' => $this->_user->trueName, 'claimtime' => time(), 'status' => Dao_Td_Tudu_Tudu::STATUS_DOING)); if (Tudu_Model::hasResource(Tudu_Model::RESOURCE_CONFIG)) { $config = Tudu_Model::getResource(Tudu_Model::RESOURCE_CONFIG); if ($config['httpsqs']) { $options = $config['httpsqs']; $charset = isset($config['charset']) ? $config['charset'] : 'utf-8'; $httpsqs = new Oray_Httpsqs($options['host'], $options['port'], $charset, $options['name']); $notifyTo = array($tudu->sender); $notifyTo = array_merge($notifyTo, array_keys($tudu->to)); if ($tudu->notifyAll) { $notifyTo = array_merge($notifyTo, array_keys($tudu->cc)); } $tpl = <<<HTML <strong>您刚收到一个新的回复</strong><br /> <a href="http://{$this->_user->domainName}/frame#m=view&tid=%s&page=1" target="_blank" _tid="{$tuduId}">%s</a><br /> 发起人:{$this->_user->trueName}<br /> 更新日期:%s<br /> {$content} HTML; $data = implode(' ', array('tudu', 'reply', '', http_build_query(array('tuduid' => $tudu->tuduId, 'from' => $userName, 'to' => implode(',', $notifyTo), 'content' => sprintf($tpl, $tudu->tuduId, $tudu->subject, date('Y-m-d H:i:s', time())))))); $httpsqs->put($data); } } }
/** * 周期任务/会议 * 图度数据 * * @param $tudu * @param $fromUnId */ public function getCycleTuduParams($tudu, $cycle, $to, $fromUnId, $time) { // 基本参数 return array('orgid' => $tudu->orgId, 'boardid' => $tudu->boardId, 'classid' => $tudu->classId, 'tuduid' => Dao_Td_Tudu_Tudu::getTuduId(), 'special' => Dao_Td_Tudu_Tudu::SPECIAL_CYCLE, 'cycleid' => $cycle->cycleId, 'uniqueid' => $fromUnId, 'email' => $tudu->sender, 'type' => $tudu->type, 'subject' => $tudu->subject, 'from' => $tudu->from[3] . ' ' . $tudu->from[0], 'to' => implode("\n", $to), 'priority' => $tudu->priority, 'privacy' => $tudu->privacy, 'status' => Dao_Td_Tudu_Tudu::STATUS_UNSTART, 'content' => $tudu->content, 'poster' => $tudu->from[0], 'posterinfo' => $tudu->posterInfo, 'lastposter' => $tudu->from[0], 'lastposttime' => time(), 'starttime' => $time[0], 'endtime' => $time[1], 'createtime' => time(), 'password' => $tudu->password, 'isauth' => $tudu->isAuth, 'cyclenum' => $tudu->cycleNum + 1, 'stepid' => Dao_Td_Tudu_Step::getStepId(), 'stepnum' => 1, 'issend' => 1, 'acceptmode' => $tudu->acceptMode, 'needconfirm' => $tudu->needConfirm, 'attachment' => array(), 'file' => array()); }
/** * 处理工作流任务的转发 * * @param Tudu_Tudu_Storage_Tudu $tudu */ public function forwardTuduFlow(Tudu_Tudu_Storage_Tudu &$tudu) { /* @var $daoStep Dao_Td_Tudu_Flow */ $daoStep = Tudu_Dao_Manager::getDao('Dao_Td_Tudu_Step', Tudu_Dao_Manager::DB_TS); $steps = $daoStep->getSteps(array('tuduid' => $tudu->tuduId))->toArray('stepid'); if (!isset($steps[$tudu->stepId])) { return; } $currentStep = $steps[$tudu->stepId]; $nextStep = isset($steps[$currentStep['nextstepid']]) ? $steps[$currentStep['nextstepid']] : null; $to = $tudu->to; $fistStepId = null; $lastStepId = null; $count = 0; $steps = array(); $to = array($to); foreach ($to as $arr) { $stepId = Dao_Td_Tudu_Step::getStepId(); $step = array('orgid' => $tudu->orgId, 'tuduid' => $tudu->tuduId, 'uniqueid' => $tudu->uniqueId, 'stepid' => $stepId, 'prevstepid' => $tudu->stepId, 'nextstepid' => $currentStep['nextstepid'], 'type' => Dao_Td_Tudu_Step::TYPE_EXECUTE, 'ordernum' => $currentStep['ordernum'] + $count + 1, 'createtime' => time()); $users = array(); foreach ($arr as $userName => $u) { $users[] = array('email' => $u['email'], 'truename' => $u['truename']); } $step['users'] = $users; if ($count == 0) { $firstStepId = $stepId; } $count++; $steps[] = $step; } $lastStepId = $stepId; $daoStep->updateStep($tudu->tuduId, $currentStep['stepid'], array('nextstepid' => $stepId)); $daoStep->updateStep($tudu->tuduId, $currentStep['nextstepid'], array('prevstepid' => $stepId)); if (null != $nextStep) { $daoStep->updateNextStepsOrder($tudu->tuduId, $nextStep['ordernum'], $count); } foreach ($steps as $step) { if ($this->createStep($step)) { $recipients = $this->prepareRecipients($tudu->orgId, $tudu->uniqueId, $step['users']); $processIndex = $step['type'] == Dao_Td_Tudu_Step::TYPE_EXAMINE ? 0 : null; $this->addStepUsers($tudu->tuduId, $step['stepid'], $recipients, $processIndex); } } /* @var $daoStep Dao_Td_Tudu_Tudu */ //$daoTudu = Tudu_Dao_Manager::getDao('Dao_Td_Tudu_Tudu', Tudu_Dao_Manager::DB_TS); //$daoTudu->updateTudu($tudu->tuduId, array('stepid' => $firstStepId)); $tudu->stepId = $firstStepId; }
/** * 更新图度步骤 * XXX * * @param Tudu_Model_Tudu_Entity_Tudu $tudu */ protected function _updateTuduSteps(Tudu_Model_Tudu_Entity_Tudu $tudu) { $daoStep = Tudu_Dao_Manager::getDao('Dao_Td_Tudu_Step', Tudu_Dao_Manager::DB_TS); if ($tudu->flowId) { return true; } $steps = $daoStep->getSteps(array('tuduid' => $tudu->tuduId))->toArray('stepid'); $currentStep = $tudu->stepId && false === strpos($tudu->stepId, '^') ? $steps[$tudu->stepId] : array_pop($steps); // 当前为审批步骤 $stepNum = count($steps); $newSteps = array(); if ($currentStep['type'] == Dao_Td_Tudu_Step::TYPE_EXAMINE) { $nextStepId = $currentStep['stepid']; $execStepId = Dao_Td_Tudu_Step::getStepId(); if ($tudu->reviewer) { $reviewers = $tudu->reviewer; $users = array(); $processIndex = 1; foreach ($reviewers as $item) { foreach ($item as $reviewer) { $users[] = array('email' => $reviewer['email'], 'truename' => $reviewer['truename'], 'processindex' => $processIndex, 'stepstatus' => $processIndex == 1 ? 1 : 0); } $processIndex++; } // 更新审批步骤审批人 $this->updateStepUsers($tudu, $currentStep['stepid'], $users); $prevStepId = $currentStep['stepid']; $tudu->stepId = $currentStep['stepid']; } else { // 审批步骤作废 //$this->cancelStep($tudu, $currentStep['stepid']); $this->updateStepUsers($tudu, $currentStep['stepid'], array()); $prevStepId = $currentStep['prevstepid']; $tudu->stepId = $execStepId; } $nextStepId = $execStepId; $newSteps[] = array('orgid' => $tudu->orgId, 'tuduid' => $tudu->tuduId, 'stepid' => $execStepId, 'uniqueid' => $tudu->uniqueId, 'prevstepid' => $prevStepId, 'nextstepid' => self::NODE_END, 'type' => $tudu->acceptMode ? Dao_Td_Tudu_Step::TYPE_CLAIM : Dao_Td_Tudu_Step::TYPE_EXECUTE, 'ordernum' => $currentStep['ordernum'] + 1, 'createtime' => time(), 'users' => $tudu->to); // 其他 } else { // 步骤作废 $prevStepId = $currentStep['stepid']; $nextStepId = null; $prevId = $prevStepId; $orderNum = $currentStep['ordernum']; if ($tudu->reviewer) { // 前一步骤作废 $this->updateStep($tudu->tuduId, $prevId, array('status' => 4)); $reviewers = $tudu->reviewer; $users = array(); $processIndex = 1; foreach ($reviewers as $item) { foreach ($item as $reviewer) { $users[] = array('email' => $reviewer['email'], 'truename' => $reviewer['truename'], 'processindex' => $processIndex); } $processIndex++; } // 前一步骤作废 $this->updateStep($tudu->tuduId, $prevId, array('status' => 4)); $stepId = Dao_Td_Tudu_Step::getStepId(); $nextStepId = Dao_Td_Tudu_Step::getStepId(); $newSteps[$stepId] = array('orgid' => $tudu->orgId, 'tuduid' => $tudu->tuduId, 'stepid' => $stepId, 'uniqueid' => $tudu->uniqueId, 'prevstepid' => $prevId, 'nextstepid' => $nextStepId, 'type' => Dao_Td_Tudu_Step::TYPE_EXECUTE, 'ordernum' => ++$orderNum, 'createtime' => time(), 'users' => array(0 => array('email' => $tudu->email, 'truename' => $tudu->poster))); $prevId = $stepId; $stepId = $nextStepId; $newSteps[$stepId] = array('orgid' => $tudu->orgId, 'tuduid' => $tudu->tuduId, 'stepid' => $stepId, 'uniqueid' => $tudu->uniqueId, 'prevstepid' => $prevId, 'nextstepid' => '^end', 'type' => Dao_Td_Tudu_Step::TYPE_EXAMINE, 'ordernum' => ++$orderNum, 'createtime' => time(), 'users' => $users); $prevId = $stepId; if (!$nextStepId) { $nextStepId = $stepId; } } if ($tudu->isChange('to') || count($newSteps) || $tudu->isChange('acceptmode')) { $stepId = Dao_Td_Tudu_Step::getStepId(); if (isset($newSteps[$prevId])) { $newSteps[$prevId]['nextstepid'] = $stepId; } $newSteps[$stepId] = array('orgid' => $tudu->orgId, 'tuduid' => $tudu->tuduId, 'stepid' => $stepId, 'uniqueid' => $tudu->uniqueId, 'prevstepid' => $prevId, 'nextstepid' => '^end', 'type' => $tudu->acceptMode ? Dao_Td_Tudu_Step::TYPE_CLAIM : Dao_Td_Tudu_Step::TYPE_EXECUTE, 'ordernum' => ++$orderNum, 'createtime' => time(), 'users' => $tudu->to); if (!$nextStepId) { $nextStepId = $stepId; } } if ($nextStepId) { $tudu->stepId = $nextStepId; } } // 移除后随未开始执行的步骤 foreach ($steps as $step) { if ($step['ordernum'] > $currentStep['ordernum']) { $this->deleteStep($tudu->tuduId, $step['stepid']); $stepNum--; } } foreach ($newSteps as $step) { if ($this->createStep($step)) { $recipients = $this->prepareRecipients($tudu->orgId, $tudu->uniqueId, $step['users']); $processIndex = $step['type'] == Dao_Td_Tudu_Step::TYPE_EXAMINE ? 0 : null; $this->addStepUsers($tudu->tuduId, $step['stepid'], $recipients, $processIndex); $stepNum++; } } $this->updateStep($tudu->tuduId, $prevStepId, array('nextstepid' => $nextStepId)); $tudu->stepNum = $stepNum; }
public function prevSave(Tudu_Model_Tudu_Entity_Tudu $tudu, Tudu_Model_Tudu_Entity_Extension_Abstract &$data) { $steps = $data->getSteps(); $currentStepId = null; // 没有预订流程,按照图度参数生成流程步骤 if (empty($steps)) { $steps = array(); $orderNum = 1; if ($tudu->reviewer) { $stepId = Dao_Td_Tudu_Step::getStepId(); $reviewStep = new Tudu_Model_Tudu_Entity_Step(array('orgid' => $tudu->orgId, 'tuduid' => $tudu->tuduId, 'uniqueid' => $tudu->uniqueId, 'stepid' => $stepId, 'type' => Dao_Td_Tudu_Step::TYPE_EXAMINE, 'prevstepid' => self::NODE_HEAD, 'nextstepid' => self::NODE_END, 'ordernum' => $orderNum++)); foreach ($tudu->reviewer as $sec) { $reviewStep->addSection($sec); } $steps[$stepId] = $reviewStep; $currentStepId = $stepId; } if ($tudu->to) { $stepId = Dao_Td_Tudu_Step::getStepId(); $prevId = self::NODE_HEAD; if ($currentStepId) { $steps[$currentStepId]->nextStepId = $stepId; $prevId = $currentStepId; } else { $currentStepId = $stepId; } $step = new Tudu_Model_Tudu_Entity_Step(array('orgid' => $tudu->orgId, 'tuduid' => $tudu->tuduId, 'uniqueid' => $tudu->uniqueId, 'stepid' => $stepId, 'type' => $tudu->acceptMode ? Dao_Td_Tudu_Step::TYPE_CLAIM : Dao_Td_Tudu_Step::TYPE_EXECUTE, 'prevstepid' => $prevId, 'nextstepid' => self::NODE_END, 'ordernum' => $orderNum++)); $sec = array(); foreach ($tudu->to as $user) { $sec[] = $user; } $step->addSection($sec); $steps[$stepId] = $step; } } else { $from = explode(' ', $tudu->target); $prevUsers = array(array('email' => $from[0], 'truename' => $from[1])); $addressBook = Tudu_AddressBook::getInstance(); foreach ($steps as $step) { $users = $step->getAttribute('users'); // 解析步骤人员 if (is_string($users)) { if (0 === strpos($users, '^')) { foreach ($prevUsers as $u) { $u = $addressBook->searchUser($tudu->orgId, $u['email']); $sections = $this->_getHeigherUsers($u['email'], $tudu->orgId, $u['deptid'] === null ? '^root' : $u['deptid'], $users == '^uppers'); if (null === $sections) { require_once 'Tudu/Model/Tudu/Exception.php'; throw new Tudu_Model_Tudu_Exception('Missing flow steps upper reviewer'); } } } else { $sections = $this->parseStepUsers($steps, $users); } } $step->setAttribute('tuduid', $tudu->tuduId); $step->setAttribute('orgid', $tudu->orgId); foreach ($sections as $section) { $step->addSection($section); } $prevUsers = array_pop($sections); } } $data->setAttribute('flowsteps', $steps); }