PageRenderTime 57ms CodeModel.GetById 17ms RepoModel.GetById 0ms app.codeStats 1ms

/scripts/task/library/Task/Httpsqs/Tudu.php

https://github.com/polokk/tudu-web-1
PHP | 2046 lines | 1539 code | 289 blank | 218 comment | 295 complexity | 0418c909600e96d13bc57ec031503b09 MD5 | raw file
  1. <?php
  2. /**
  3. * Task_Httpsqs
  4. *
  5. * LICENSE
  6. *
  7. *
  8. * @category Task_Httpsqs_Tudu
  9. * @package Task_Httpsqs_Tudu
  10. * @copyright Copyright (c) 2011-2011 Shanghai Best Oray Information S&T CO., Ltd.
  11. * @link http://www.tudu.com/
  12. * @version $Id: Tudu.php 2809 2013-04-07 09:57:05Z cutecube $
  13. */
  14. /**
  15. * 后台处理脚本
  16. * * * 创建图度
  17. * * * 更新图度
  18. * * * 回复图度
  19. * * * 确认图度
  20. *
  21. * @category Task_Httpsqs_Tudu
  22. * @package Task_Httpsqs_Tudu
  23. * @copyright Copyright (c) 2011-2011 Shanghai Best Oray Information S&T CO., Ltd.
  24. */
  25. class Task_Httpsqs_Tudu extends Task_Abstract
  26. {
  27. /**
  28. *
  29. * @var Oray_Httpsqs
  30. */
  31. protected $_httpsqs = null;
  32. /**
  33. *
  34. * @var Oray_Memcache
  35. */
  36. protected $_memcache = null;
  37. /**
  38. *
  39. * @var array
  40. */
  41. protected $_tsDbs = array();
  42. /**
  43. *
  44. * @var string
  45. */
  46. protected $_unId = '^system';
  47. /**
  48. *
  49. * @var 类型列表
  50. */
  51. protected $_typeNames = array(
  52. 'tudu' => '图度',
  53. 'task' => '图度',
  54. 'discuss' => '讨论',
  55. 'notice' => '公告',
  56. 'meeting' => '会议'
  57. );
  58. /**
  59. *
  60. */
  61. public function startUp()
  62. {
  63. foreach ($this->_options['multidb'] as $key => $item) {
  64. if (0 === strpos($key, 'ts')) {
  65. $this->_tsDbs[$key] = Zend_Db::factory($item['adapter'], $item['params']);
  66. continue ;
  67. }
  68. Tudu_Dao_Manager::setDb($key, Zend_Db::factory($item['adapter'], $item['params']));
  69. }
  70. $this->_memcache = new Oray_Memcache(array(
  71. 'compression' => $this->_options['memcache']['compression'],
  72. 'compatibility' => $this->_options['memcache']['compatibility']
  73. ));
  74. $this->_memcache->addServer(
  75. $this->_options['memcache']['host'],
  76. $this->_options['memcache']['port']
  77. );
  78. $this->_httpsqs = new Oray_Httpsqs(
  79. $this->_options['httpsqs']['host'],
  80. $this->_options['httpsqs']['port'],
  81. $this->_options['httpsqs']['charset'],
  82. $this->_options['httpsqs']['names']['tudu']
  83. );
  84. }
  85. /**
  86. *
  87. */
  88. public function shutDown()
  89. {
  90. $this->_httpsqs->closeConnection();
  91. }
  92. /**
  93. * 执行
  94. */
  95. public function run()
  96. {
  97. do {
  98. $data = $this->_httpsqs->get($this->_options['httpsqs']['names']['tudu']);
  99. if (!$data || $data == 'HTTPSQS_GET_END') {
  100. break ;
  101. }
  102. list($module, $action, $sub, $query) = explode(' ', $data);
  103. parse_str($query, $query);
  104. if ($module !== 'tudu') {
  105. $this->getLogger()->warn("Invalid param \"module\" values {$module}");
  106. }
  107. if (empty($query['tsid'])) {
  108. $this->getLogger()->warn("Missing param \"tsid\"");
  109. continue ;
  110. }
  111. if (!isset($this->_tsDbs['ts' . $query['tsid']])) {
  112. return ;
  113. }
  114. $tsId = $query['tsid'];
  115. Tudu_Dao_Manager::setDb(Tudu_Dao_Manager::DB_TS, $this->_tsDbs['ts' . $tsId]);
  116. switch ($action) {
  117. case 'create':
  118. $this->createTudu($query);
  119. break;
  120. case 'update':
  121. $this->updateTudu($query);
  122. break ;
  123. case 'review':
  124. $this->reviewTudu($query);
  125. break;
  126. case 'reply':
  127. $this->reply($query);
  128. break;
  129. case 'confirm':
  130. $this->doneTudu($query);
  131. break;
  132. case 'filter':
  133. $this->filterTudu($query);
  134. break;
  135. case 'rule':
  136. $this->updateRules($query);
  137. break;
  138. case 'cycle':
  139. $this->cycle($query);
  140. break;
  141. default:
  142. $this->getLogger()->info("Invalid action values {$action}");
  143. break;
  144. }
  145. } while (true);
  146. }
  147. /**
  148. * 创建图度
  149. *
  150. * 检查、保存外部联系人
  151. * 构造图度talk通知内容和参数
  152. * 分发其他相关操作队列
  153. * 1、IM通知
  154. * 2、图度收发规则
  155. * 3、外发邮件
  156. * 4、自动确认
  157. */
  158. public function createTudu($params)
  159. {
  160. if (empty($params['tuduid'])
  161. || empty($params['server'])
  162. || empty($params['tsid'])
  163. || empty($params['from'])
  164. || empty($params['uniqueid']))
  165. {
  166. return ;
  167. }
  168. $tuduId = $params['tuduid'];
  169. $tsId = $params['tsid'];
  170. $server = $params['server'];
  171. $from = $params['from'];
  172. $uniqueId = $params['uniqueid'];
  173. $manager = Tudu_Tudu_Manager::getInstance(Tudu_Dao_Manager::getDb(Tudu_Dao_Manager::DB_TS));
  174. $tudu = $manager->getTuduById($tuduId, $this->_unId);
  175. // 不存在
  176. if (null === $tudu) {
  177. $this->getLogger()->warn("Tudu id:{$tuduId} is not exists");
  178. return ;
  179. }
  180. // 查找通知接收人
  181. $users = $manager->getTuduUsers($tuduId, array('isfroeign' => 0));
  182. $notifyTo = array();
  183. foreach ($users as $user) {
  184. $notifyTo[] = $user['email'];
  185. }
  186. // 添加常用版块
  187. $daoBoard = Tudu_Dao_Manager::getDao('Dao_Td_Board_Board', Tudu_Dao_Manager::DB_TS);
  188. $favor = $daoBoard->getFavor($tudu->orgId, $tudu->boardId, $uniqueId);
  189. $weight = 0;
  190. if (null === $favor) {
  191. $daoBoard->addFavor(array(
  192. 'orgid' => $tudu->orgId,
  193. 'boardid' => $tudu->boardId,
  194. 'uniqueid' => $uniqueId,
  195. 'weight' => 1
  196. ));
  197. // 已存在的增加权重
  198. } else {
  199. if ($favor['weight'] < Dao_Td_Board_Board::FAVOR_WEIGHT_LIMIT) {
  200. $daoBoard->updateFavor($tudu->orgId, $tudu->boardId, $uniqueId, array(
  201. 'weight' => $favor['weight'] + 1
  202. ));
  203. }
  204. }
  205. // 最多五个
  206. $boards = $daoBoard->getBoards(array(
  207. 'orgid' => $tudu->orgId,
  208. 'uniqueid' => $uniqueId
  209. ), array('weight' => 1))->toArray();
  210. $autoFavor = array();
  211. foreach ($boards as $item) {
  212. if ($item['weight'] >= Dao_Td_Board_Board::FAVOR_WEIGHT_LIMIT) {
  213. continue ;
  214. }
  215. $autoFavor[$item['boardid']] = $tudu->boardId == $item['boardid'] ? $item['weight'] + 1 : $item['weight'];
  216. }
  217. $count = count($autoFavor);
  218. if ($count > 5 && arsort($autoFavor)) {
  219. $counter = 0;
  220. $spliced = array_splice($autoFavor, 5);
  221. $minWeight = end($autoFavor);
  222. $offset = $minWeight - 5;
  223. if ($offset >= 0) {
  224. foreach ($autoFavor as $bid => $weight) {
  225. $daoBoard->updateFavor($tudu->orgId, $bid, $uniqueId, array('weight' => $weight - $offset));
  226. }
  227. foreach ($spliced as $bid => $weight) {
  228. $weight -= $offset;
  229. if ($weight <= 0) {
  230. $daoBoard->deleteFavor($tudu->orgId, $bid, $uniqueId);
  231. continue ;
  232. }
  233. if ($weight == 5 || $tudu->boardId == $bid) {
  234. $weight --;
  235. }
  236. $daoBoard->updateFavor($tudu->orgId, $bid, $uniqueId, array('weight' => $weight));
  237. }
  238. }
  239. }
  240. // 常用工作流
  241. if ($tudu->flowId) {
  242. $daoFlow = Tudu_Dao_Manager::getDao('Dao_Td_Flow_Flow', Tudu_Dao_Manager::DB_TS);
  243. $flowFavor = $daoFlow->getFavor($tudu->flowId, $uniqueId);
  244. if (null === $flowFavor) {
  245. $daoFlow->addFavor($tudu->flowId, $uniqueId);
  246. } else {
  247. $daoFlow->updateFavor($tudu->flowId, $uniqueId, array(
  248. 'weight' => $flowFavor['weight'] + 1,
  249. 'updatetime' => time()
  250. ));
  251. }
  252. }
  253. // 工作流回复
  254. if (!empty($params['flowid']) && !empty($params['nstepid'])) {
  255. $flowId = $params['flowid'];
  256. $stepId = $params['nstepid'];
  257. $types = array(
  258. 0 => '执行',
  259. 1 => '审批',
  260. 2 => '认领'
  261. );
  262. $typeText = array(
  263. 0 => '执行本任务',
  264. 1 => '对本任务进行审批',
  265. 2 => '对本任务进行认领'
  266. );
  267. $daoFlow = Tudu_Dao_Manager::getDao('Dao_Td_Flow_Flow', Tudu_Dao_Manager::DB_TS);
  268. $daoTuduFlow = Tudu_Dao_Manager::getDao('Dao_Td_Tudu_Flow', Tudu_Dao_Manager::DB_TS);
  269. $flow = $daoFlow->getFlowById($flowId);
  270. if (null != $flow) {
  271. $flow = $flow->toArray();
  272. //$users = $daoStep->getUsers($tuduId, $stepId);
  273. $tuduFlow = $daoTuduFlow->getFlow(array('tuduid' => $tuduId));
  274. //$step = $flow['steps'][$stepId];
  275. foreach ($flow['steps'] as $item) {
  276. if ($item['stepid'] == $stepId) {
  277. $step = $item;
  278. }
  279. }
  280. $names = array();
  281. if (isset($tuduFlow->steps[$stepId])) {
  282. $st = $tuduFlow->steps[$stepId];
  283. $users = $st['section'][$st['currentSection']];
  284. foreach ($users as $user) {
  285. $names[] = $user['truename'];
  286. }
  287. }
  288. $names = implode(',', $names);
  289. if ($step) {
  290. // 处理描述换行
  291. $description = nl2br($step['description']);
  292. $content = <<<POST
  293. <div class="tudu_sysinfo_wrap tudu_sys_pass"><div class="tudu_sysinfo_border"></div><div class="tudu_sysinfo_corner"></div>
  294. <div class="tudu_sysinfo_body">
  295. <div class="tudu_sysinfo_wrap">
  296. <div class="tudu_sysinfo_icon"></div>
  297. <div class="tudu_sysinfo_content">
  298. <p><strong>{$types[$step['type']]}</strong>&nbsp;{$names}&nbsp;{$typeText[$step['type']]}</p>
  299. <p><strong>{$step['subject']}</strong></p>
  300. <p><strong>描述</strong>{$description}</p>
  301. </div>
  302. </div>
  303. <div class="tudu_sysinfo_clear"></div>
  304. </div>
  305. <div class="tudu_sysinfo_corner"></div><div class="tudu_sysinfo_border"></div></div>
  306. POST;
  307. // 构造参数
  308. $post = array(
  309. 'orgid' => $tudu->orgId,
  310. 'boardid' => $tudu->boardId,
  311. 'tuduid' => $tudu->tuduId,
  312. 'uniqueid' => '^system',
  313. 'email' => 'robot@oray.com',
  314. 'poster' => '图度系统',
  315. 'posterinfo' => '',
  316. 'content' => $content
  317. );
  318. $storage = Tudu_Tudu_Storage::getInstance();
  319. $postId = $storage->createPost($post);
  320. $manager->sendPost($tuduId, $postId);
  321. }
  322. }
  323. }
  324. $notifyTo = array_unique(array_diff($notifyTo, array($from)));
  325. // 发送提醒
  326. $this->sendTuduNotify('create', $tudu, $from, $server, $notifyTo);
  327. // 处理ios推送
  328. $this->_httpsqs->put(implode(' ', array(
  329. 'tudu',
  330. 'create',
  331. '',
  332. http_build_query(array(
  333. 'orgid' => $tudu->orgId,
  334. 'tsid' => $tsId,
  335. 'tuduid' => $tuduId,
  336. 'subject'=> $tudu->subject,
  337. 'alertto'=> $notifyTo,
  338. 'type' => $tudu->type
  339. ))
  340. )), 'notify');
  341. // 执行图度规则
  342. $this->_httpsqs->put(implode(' ', array(
  343. 'tudu',
  344. 'filter',
  345. '',
  346. http_build_query(array(
  347. 'tsid' => $tsId,
  348. 'tuduid' => $tuduId
  349. ))
  350. )), $this->_options['httpsqs']['names']['tudu']);
  351. // 执行外发
  352. $this->_httpsqs->put(implode(' ', array(
  353. 'send',
  354. 'tudu',
  355. '',
  356. http_build_query(array(
  357. 'tsid' => $tsId,
  358. 'tuduid' => $tuduId,
  359. 'uniqueid' => $uniqueId,
  360. 'to' => '',
  361. 'act' => null
  362. ))
  363. )), $this->_options['httpsqs']['names']['send']);
  364. // 发送时就已完成
  365. if ($tudu->isDone && $tudu->parentId) {
  366. $this->_httpsqs->put(implode(' ', array(
  367. 'tudu',
  368. 'confirm',
  369. '',
  370. http_build_query(array(
  371. 'tsid' => $tsId,
  372. 'tuduid' => $tudu->parentId
  373. ))
  374. )), $this->_options['httpsqs']['names']['tudu']);
  375. }
  376. $this->getLogger()->debug("Tudu id:{$tuduId} done");
  377. }
  378. /**
  379. * 更新图度
  380. *
  381. *
  382. * @param $params
  383. */
  384. public function updateTudu($params)
  385. {
  386. if (empty($params['tuduid'])
  387. || empty($params['server'])
  388. || empty($params['tsid'])
  389. || empty($params['from'])
  390. || empty($params['uniqueid']))
  391. {
  392. return ;
  393. }
  394. $tuduId = $params['tuduid'];
  395. $tsId = $params['tsid'];
  396. $server = $params['server'];
  397. $from = $params['from'];
  398. $uniqueId = $params['uniqueid'];
  399. $isChangedCc = $params['ischangedCc'];
  400. $manager = Tudu_Tudu_Manager::getInstance(Tudu_Dao_Manager::getDb(Tudu_Dao_Manager::DB_TS));
  401. $tudu = $manager->getTuduById($tuduId, $this->_unId);
  402. // 不存在
  403. if (null === $tudu) {
  404. $this->getLogger()->warn("Tudu id:{$tuduId} is not exists");
  405. return ;
  406. }
  407. $isReview = false;
  408. if ($tudu->type == 'notice' && strpos($tudu->stepId, '^') !== 0) {
  409. $isReview = true;
  410. }
  411. // 查找通知接收人
  412. $filter = array('isforeign' => 0);
  413. // 更新讨论时,默认提醒全部
  414. if (!$tudu->type == 'discuss' && !$tudu->notifyAll && !$isChangedCc && !$isReview) {
  415. $filter['role'] = 'to';
  416. }
  417. $users = $manager->getTuduUsers($tuduId, $filter);
  418. $notifyTo = array();
  419. foreach ($users as $user) {
  420. $notifyTo[] = $user['email'];
  421. }
  422. $notifyTo = array_unique(array_diff($notifyTo, array($from)));
  423. // 发送提醒
  424. $this->sendTuduNotify('update', $tudu, $from, $server, $notifyTo);
  425. // 处理ios推送
  426. $this->_httpsqs->put(implode(' ', array(
  427. 'tudu',
  428. 'update',
  429. '',
  430. http_build_query(array(
  431. 'orgid' => $tudu->orgId,
  432. 'tsid' => $tsId,
  433. 'tuduid' => $tuduId,
  434. 'subject'=> $tudu->subject,
  435. 'alertto'=> $notifyTo,
  436. 'type' => $tudu->type
  437. ))
  438. )), 'notify');
  439. // 执行图度规则
  440. $this->_httpsqs->put(implode(' ', array(
  441. 'tudu',
  442. 'filter',
  443. '',
  444. http_build_query(array(
  445. 'tsid' => $tsId,
  446. 'tuduid' => $tuduId
  447. ))
  448. )), $this->_options['httpsqs']['names']['tudu']);
  449. // 执行外发
  450. $this->_httpsqs->put(implode(' ', array(
  451. 'send',
  452. 'tudu',
  453. '',
  454. http_build_query(array(
  455. 'tsid' => $tsId,
  456. 'tuduid' => $tuduId,
  457. 'uniqueid' => $uniqueId,
  458. 'to' => '',
  459. 'act' => null
  460. ))
  461. )), $this->_options['httpsqs']['names']['send']);
  462. // 发送时就已完成
  463. if ($tudu->isDone && $tudu->parentId) {
  464. $this->_httpsqs->put(implode(' ', array(
  465. 'tudu',
  466. 'confirm',
  467. '',
  468. http_build_query(array(
  469. 'tsid' => $tsId,
  470. 'tuduid' => $tudu->parentId
  471. ))
  472. )), $this->_options['httpsqs']['names']['tudu']);
  473. }
  474. // 100的周期任务
  475. if ($tudu->percent >= 100 && $tudu->cycleId) {
  476. $daoCycle = Tudu_Dao_Manager::getDao('Dao_Td_Tudu_Cycle', Tudu_Dao_Manager::DB_TS);
  477. $cycle = $daoCycle->getCycle(array('cycleid' => $tudu->cycleId));
  478. if (null === $cycle) {
  479. $this->getLogger()->warn("Tudu Cycle id: {$tudu->cycleId} is not exists");
  480. return ;
  481. }
  482. // 当前周期循环次数,发送下一周期
  483. if ($cycle && $cycle->count == $tudu->cycleNum) {
  484. $this->_httpsqs->put(implode(' ', array(
  485. 'tudu',
  486. 'cycle',
  487. '',
  488. http_build_query(array(
  489. 'tsid' => $tsId,
  490. 'tuduid' => $tudu->tuduId,
  491. 'cycleid' => $tudu->cycleId
  492. ))
  493. )), $this->_options['httpsqs']['names']['tudu']);
  494. }
  495. }
  496. $this->getLogger()->debug("Tudu id:{$tuduId} done");
  497. }
  498. /**
  499. * 审批相关操作
  500. *
  501. * @param $params
  502. */
  503. public function reviewTudu($params)
  504. {
  505. if (empty($params['tuduid'])
  506. || empty($params['tsid'])
  507. || empty($params['uniqueid'])
  508. || empty($params['from'])
  509. || empty($params['type'])
  510. || empty($params['stepid'])
  511. || !isset($params['agree']))
  512. {
  513. return ;
  514. }
  515. $tuduId = $params['tuduid'];
  516. $from = $params['from'];
  517. $uniqueId = $params['uniqueid'];
  518. $tsId = $params['tsid'];
  519. $server = $params['server'];
  520. $type = $params['type'];
  521. $isChangedCc = $params['ischangedCc'];
  522. $stepId = $params['stepid'];
  523. $agree = $params['agree'];
  524. $manager = Tudu_Tudu_Manager::getInstance(Tudu_Dao_Manager::getDb(Tudu_Dao_Manager::DB_TS));
  525. $tudu = $manager->getTuduById($tuduId, $this->_options['httpsqs']['names']['im']);
  526. if (null === $tudu) {
  527. $this->getLogger()->warn("Tudu id: {$tuduId} is not eixsts");
  528. return ;
  529. }
  530. //$daoStep = Tudu_Dao_Manager::getDao('Dao_Td_Tudu_Step', Tudu_Dao_Manager::DB_TS);
  531. $daoFlow = Tudu_Dao_Manager::getDao('Dao_Td_Tudu_Flow', Tudu_Dao_Manager::DB_TS);
  532. // 同意审批,通知下一步审批人或执行人
  533. $to = array();
  534. if ($agree) {
  535. $flow = $daoFlow->getFlow(array('tuduid' => $tuduId));
  536. $currStep = isset($flow->steps[$flow->currentStepId]) ? $flow->steps[$flow->currentStepId] : null;
  537. //$stepUsers = $daoStep->getUsers($tuduId, $tudu->stepId);
  538. // 审批人
  539. if ($currStep['type'] == Dao_Td_Tudu_Step::TYPE_EXAMINE) {
  540. foreach ($currStep['section'] as $sec) {
  541. foreach ($sec as $user) {
  542. if ($user['status'] == 1) {
  543. $info = explode(' ', $user['userinfo']);
  544. $to[] = $info[0];
  545. }
  546. }
  547. }
  548. // 执行人
  549. } elseif($currStep['type'] == Dao_Td_Tudu_Step::TYPE_EXECUTE) {
  550. if ($tudu->type == 'notice') {
  551. $accepters = $manager->getTuduUsers($tuduId);
  552. foreach ($accepters as $item) {
  553. $to[] = $item['email'];
  554. }
  555. } else {
  556. foreach ($currStep['section'][0] as $user) {
  557. //$info = explode(' ', $user['userinfo']);
  558. $to[] = $user['username'];
  559. }
  560. }
  561. }
  562. $to = array_unique($to);
  563. // 工作流回复
  564. if (!empty($params['flowid']) && !empty($params['nstepid']) && !empty($params['stepstatus'])) {
  565. $flowId = $params['flowid'];
  566. $stepId = $params['nstepid'];
  567. $types = array(
  568. 0 => '执行',
  569. 1 => '审批',
  570. 2 => '认领'
  571. );
  572. $typeText = array(
  573. 0 => '执行本任务',
  574. 1 => '对本任务进行审批',
  575. 2 => '对本任务进行认领'
  576. );
  577. $daoFlow = Tudu_Dao_Manager::getDao('Dao_Td_Flow_Flow', Tudu_Dao_Manager::DB_TS);
  578. //$daoStep = Tudu_Dao_Manager::getDao('Dao_Td_Tudu_Step', Tudu_Dao_Manager::DB_TS);
  579. $flow = $daoFlow->getFlowById($flowId);
  580. if (null != $flow) {
  581. $flow = $flow->toArray();
  582. $users = array();
  583. $step = null;
  584. foreach ($flow['steps'] as $item) {
  585. if ($item['stepid'] == $stepId) {
  586. $step = $item;
  587. }
  588. }
  589. $names = array();
  590. foreach ($currStep['section'] as $sec) {
  591. foreach ($sec as $user) {
  592. if ($user['status'] == 1) {
  593. $names[] = $user['truename'];
  594. }
  595. }
  596. }
  597. $names = implode(',', $names);
  598. if ($step) {
  599. // 处理描述换行
  600. $description = nl2br($step['description']);
  601. $content = <<<POST
  602. <div class="tudu_sysinfo_wrap tudu_sys_pass"><div class="tudu_sysinfo_border"></div><div class="tudu_sysinfo_corner"></div>
  603. <div class="tudu_sysinfo_body">
  604. <div class="tudu_sysinfo_wrap">
  605. <div class="tudu_sysinfo_icon"></div>
  606. <div class="tudu_sysinfo_content">
  607. <p><strong>{$types[$step['type']]}</strong>&nbsp;{$names}&nbsp;{$typeText[$step['type']]}</p>
  608. <p><strong>{$step['subject']}</strong></p>
  609. <p><strong>描述</strong>{$description}</p>
  610. </div>
  611. </div>
  612. <div class="tudu_sysinfo_clear"></div>
  613. </div>
  614. <div class="tudu_sysinfo_corner"></div><div class="tudu_sysinfo_border"></div></div>
  615. POST;
  616. // 构造参数
  617. $post = array(
  618. 'orgid' => $tudu->orgId,
  619. 'boardid' => $tudu->boardId,
  620. 'tuduid' => $tudu->tuduId,
  621. 'uniqueid' => '^system',
  622. 'email' => 'robot@oray.com',
  623. 'poster' => '图度系统',
  624. 'posterinfo' => '',
  625. 'content' => $content
  626. );
  627. $storage = Tudu_Tudu_Storage::getInstance();
  628. $postId = $storage->createPost($post);
  629. $manager->sendPost($tuduId, $postId);
  630. }
  631. }
  632. }
  633. $this->sendTuduNotify('create', $tudu, $from, $server, $to);
  634. }
  635. $notifyTo = array();
  636. $notifyTo[] = $tudu->sender;
  637. $filter = array('isforeign' => 0);
  638. if (!$tudu->notifyAll && !$isChangedCc) {
  639. $filter['role'] = 'to';
  640. }
  641. $users = $manager->getTuduUsers($tuduId, $filter);
  642. foreach ($users as $user) {
  643. $notifyTo[] = $user['email'];
  644. }
  645. // 获取前一步骤用户
  646. $prevStepId = $currStep['prev'];
  647. if ($prevStepId && strpos($prevStepId, '^') !== 0) {
  648. $prevStep = isset($flow->steps[$prevStepId]) ? $flow->steps[$prevStepId] : null;
  649. //$prevStepUsers = $daoStep->getUsers($tuduId, $prevStepId);
  650. foreach ($prevStep['section'] as $sec) {
  651. foreach ($sec as $user) {
  652. $notifyTo[] = $user['username'];
  653. }
  654. }
  655. }
  656. $notifyTo = array_unique(array_diff($notifyTo, array($from)));
  657. $notifyTo = array_diff($notifyTo, $to);
  658. $this->sendReviewPostNotify($tudu, $agree, $from, $server, $notifyTo);
  659. // 处理ios推送
  660. $this->_httpsqs->put(implode(' ', array(
  661. 'post',
  662. 'create',
  663. '',
  664. http_build_query(array(
  665. 'orgid' => $tudu->orgId,
  666. 'tsid' => $tsId,
  667. 'tuduid' => $tuduId,
  668. 'subject'=> $tudu->subject,
  669. 'alertto'=> $notifyTo,
  670. 'type' => $tudu->type
  671. ))
  672. )), 'notify');
  673. // 执行图度规则
  674. $this->_httpsqs->put(implode(' ', array(
  675. 'tudu',
  676. 'filter',
  677. '',
  678. http_build_query(array(
  679. 'tsid' => $tsId,
  680. 'tuduid' => $tuduId
  681. ))
  682. )), $this->_options['httpsqs']['names']['tudu']);
  683. // 执行外发
  684. $this->_httpsqs->put(implode(' ', array(
  685. 'send',
  686. 'tudu',
  687. '',
  688. http_build_query(array(
  689. 'tsid' => $tsId,
  690. 'tuduid' => $tuduId,
  691. 'uniqueid' => $uniqueId,
  692. 'to' => '',
  693. 'act' => null
  694. ))
  695. )), $this->_options['httpsqs']['names']['send']);
  696. // 已完成
  697. if ($tudu->isDone && $tudu->parentId) {
  698. $this->_httpsqs->put(implode(' ', array(
  699. 'tudu',
  700. 'confirm',
  701. '',
  702. http_build_query(array(
  703. 'tsid' => $tsId,
  704. 'tuduid' => $tudu->parentId
  705. ))
  706. )), $this->_options['httpsqs']['names']['tudu']);
  707. }
  708. $this->getLogger()->debug("Tudu id:{$tuduId} done");
  709. }
  710. /**
  711. * 回复相关操作
  712. *
  713. * @param $params
  714. */
  715. public function reply($params)
  716. {
  717. if (empty($params['tuduid'])
  718. || empty($params['postid'])
  719. || empty($params['sender'])
  720. || empty($params['uniqueid'])
  721. || empty($params['from'])
  722. || empty($params['tsid'])
  723. || empty($params['server']))
  724. {
  725. return ;
  726. }
  727. $tuduId = $params['tuduid'];
  728. $postId = $params['postid'];
  729. $sender = $params['sender'];
  730. $uniqueId = $params['uniqueid'];
  731. $from = $params['from'];
  732. $tsId = $params['tsid'];
  733. $server = $params['server'];
  734. $manager = Tudu_Tudu_Manager::getInstance(Tudu_Dao_Manager::getDb(Tudu_Dao_Manager::DB_TS));
  735. $tudu = $manager->getTuduById($tuduId, $this->_unId);
  736. if (null === $tudu) {
  737. $this->getLogger()->warn("Tudu id: {$tuduId} is not eixsts");
  738. return ;
  739. }
  740. $post = $manager->getPostById($tuduId, $postId);
  741. if (null == $post) {
  742. $this->getLogger()->warn("Post id: {$postId} is not eixsts");
  743. return ;
  744. }
  745. // 提醒相关人员 - 发送人、接收人、加星标
  746. $users = $manager->getTuduUsers($tudu->tuduId);
  747. $notifyTo = array();
  748. $isForeign = false;
  749. $daoUser = Tudu_Dao_Manager::getDao('Dao_Md_User_User', Tudu_Dao_Manager::DB_MD);
  750. foreach ($users as $item) {
  751. $labels = explode(',', $item['labels']);
  752. if ($tudu->type == 'notice' || ($tudu->type == 'discuss' && $tudu->notifyAll) || ($tudu->notifyAll || in_array('^t', $labels)) && !in_array('^n', $labels) && !$item['isforeign']) {
  753. $user = $daoUser->getUser(array('uniqueid' => $item['uniqueid']));
  754. if ($user) {
  755. $notifyTo[] = $user->userName;
  756. }
  757. }
  758. if ($item['isforeign']) {
  759. $isForeign = true;
  760. }
  761. }
  762. // 工作流回复
  763. if (!empty($params['flowid']) && !empty($params['nstepid'])) {
  764. $flowId = $params['flowid'];
  765. $stepId = $params['nstepid'];
  766. $types = array(
  767. 0 => '执行',
  768. 1 => '审批',
  769. 2 => '认领'
  770. );
  771. $typeText = array(
  772. 0 => '执行本任务',
  773. 1 => '对本任务进行审批',
  774. 2 => '对本任务进行认领'
  775. );
  776. $daoFlow = Tudu_Dao_Manager::getDao('Dao_Td_Flow_Flow', Tudu_Dao_Manager::DB_TS);
  777. //$daoStep = Tudu_Dao_Manager::getDao('Dao_Td_Tudu_Step', Tudu_Dao_Manager::DB_TS);
  778. $daoTuduFlow = Tudu_Dao_Manager::getDao('Dao_Td_Tudu_Flow', Tudu_Dao_Manager::DB_TS);
  779. $flow = $daoFlow->getFlowById($flowId);
  780. if (null != $flow) {
  781. $flow = $flow->toArray();
  782. $tuduFlow = $daoTuduFlow->getFlow(array('tuduid' => $tuduId));
  783. $step = isset($tuduFlow->steps[$tuduFlow->currentStepId]) ? $tuduFlow->steps[$tuduFlow->currentStepId] : null;
  784. $names = array();
  785. foreach ($step['section'] as $sec) {
  786. foreach ($sec as $user) {
  787. $names[] = $user['truename'];
  788. }
  789. }
  790. $names = implode(',', $names);
  791. if ($step) {
  792. $content = <<<POST
  793. <p><strong>{$types[$step['type']]}</strong>&nbsp;{$names}&nbsp;{$typeText[$step['type']]}</p>
  794. <p><strong>{$step['subject']}</strong></p>
  795. <p><strong>描述</strong>{$step['description']}</p>
  796. POST;
  797. // 构造参数
  798. $fpost = array(
  799. 'orgid' => $tudu->orgId,
  800. 'boardid' => $tudu->boardId,
  801. 'tuduid' => $tudu->tuduId,
  802. 'uniqueid' => '^system',
  803. 'email' => 'robot@oray.com',
  804. 'poster' => '图度系统',
  805. 'posterinfo' => '',
  806. 'content' => $content
  807. );
  808. $storage = Tudu_Tudu_Storage::getInstance();
  809. $postId = $storage->createPost($fpost);
  810. $manager->sendPost($tuduId, $postId);
  811. }
  812. }
  813. }
  814. $notifyTo = array_unique(array_merge($notifyTo, array($tudu->sender), $tudu->accepter));
  815. $notifyTo = array_diff($notifyTo, array($from));
  816. $this->sendPostNotify($tudu, $post, $from, $server, $notifyTo);
  817. // 处理ios推送
  818. $this->_httpsqs->put(implode(' ', array(
  819. 'post',
  820. $tudu->type,
  821. '',
  822. http_build_query(array(
  823. 'orgid' => $tudu->orgId,
  824. 'tsid' => $tsId,
  825. 'tuduid' => $tuduId,
  826. 'type' => $tudu->type,
  827. 'subject'=> $tudu->subject,
  828. 'alertto'=> $notifyTo,
  829. 'type' => $tudu->type
  830. ))
  831. )), 'notify');
  832. // 外发回复
  833. if ($isForeign) {
  834. $content = $this->getPostDescription($post);
  835. $data = implode(' ', array(
  836. 'send',
  837. 'reply',
  838. '',
  839. http_build_query(array(
  840. 'tsid' => $tsId,
  841. 'tuduid' => $tuduId,
  842. 'uniqueid' => $uniqueId,
  843. 'from' => $sender,
  844. 'content' => mb_substr(strip_tags($content), 0, 20, 'utf-8')
  845. ))
  846. ));
  847. $this->_httpsqs->put($data, $this->_options['httpsqs']['names']['send']);
  848. }
  849. // 自动确认
  850. if (!empty($params['confirm'])) {
  851. $this->_httpsqs->put(implode(' ', array(
  852. 'tudu',
  853. 'confirm',
  854. '',
  855. http_build_query(array(
  856. 'tsid' => $tsId,
  857. 'tuduid' => $tudu->parentId
  858. ))
  859. )), $this->_options['httpsqs']['names']['tudu']);
  860. }
  861. // 周期任务
  862. if (!empty($params['cycle'])) {
  863. $this->_httpsqs->put(implode(' ', array(
  864. 'tudu',
  865. 'cycle',
  866. '',
  867. http_build_query(array(
  868. 'tuduid' => $tudu->tuduId,
  869. 'tsid' => $tsId,
  870. 'cycleid' => $tudu->cycleId
  871. ))
  872. )), $this->_options['httpsqs']['names']['tudu']);
  873. }
  874. $this->getLogger()->debug("Tudu id:{$tuduId} done");
  875. }
  876. /**
  877. * 图度确认完成相关操作
  878. *
  879. * 遍历确认父级图度(如果有并且自动确认)
  880. * @param $params
  881. */
  882. public function doneTudu($params)
  883. {
  884. if (empty($params['tuduid'])
  885. || empty($params['tsid']))
  886. {
  887. return ;
  888. }
  889. $tuduId = $params['tuduid'];
  890. $tsId = $params['tsid'];
  891. $path = array();
  892. if (isset($params['path'])) {
  893. $path = explode(',', $params['path']);
  894. }
  895. $manager = Tudu_Tudu_Manager::getInstance(Tudu_Dao_Manager::getDb(Tudu_Dao_Manager::DB_TS));
  896. $tudu = $manager->getTuduById($tuduId, $this->_unId);
  897. if (null === $tudu) {
  898. $this->getLogger()->warn("Tudu id: {$tuduId} is not eixsts");
  899. return ;
  900. }
  901. if ($tudu->needConfirm == 0 && $tudu->percent >= 100) {
  902. $ret = $manager->doneTudu($tuduId, true, 0);
  903. if (!$ret) {
  904. $this->getLogger()->warn("Done Tudu failed id:{$tuduId}");
  905. }
  906. if ($tudu->parentId) {
  907. $path[] = $tuduId;
  908. if(in_array($tudu->parentId, $path)) {
  909. break;
  910. }
  911. $this->_httpsqs->put(implode(' ', array(
  912. 'tudu',
  913. 'confirm',
  914. '',
  915. http_build_query(array(
  916. 'tsid' => $tsId,
  917. 'tuduid' => $tudu->parentId,
  918. 'path' => implode(',', $path)
  919. ))
  920. )), $this->_options['httpsqs']['names']['tudu']);
  921. }
  922. }
  923. $this->getLogger()->debug("Tudu id:{$tuduId} done");
  924. }
  925. /**
  926. * 生成周期图度
  927. *
  928. * @param $params
  929. */
  930. public function cycle($params)
  931. {
  932. if (empty($params['tuduid'])
  933. || empty($params['cycleid'])
  934. || empty($params['tsid']))
  935. {
  936. return ;
  937. }
  938. $tuduId = $params['tuduid'];
  939. $cycleId = $params['cycleid'];
  940. $tsId = $params['tsid'];
  941. $daoUser = Tudu_Dao_Manager::getDao('Dao_Md_User_User', Tudu_Dao_Manager::DB_MD);
  942. $daoCycle = Tudu_Dao_Manager::getDao('Dao_Td_Tudu_Cycle', Tudu_Dao_Manager::DB_TS);
  943. $manager = Tudu_Tudu_Manager::getInstance(Tudu_Dao_Manager::getDb(Tudu_Dao_Manager::DB_TS));
  944. $tudu = $manager->getTuduById($tuduId, $this->_unId);
  945. $fromTuduId = $tudu->tuduId;
  946. $acceptMode = $tudu->acceptMode;
  947. $isAuth = $tudu->isAuth;
  948. if (null === $tudu) {
  949. $this->getLogger()->warn("Tudu id: {$tuduId} is not exists");
  950. return ;
  951. }
  952. $cycle = $daoCycle->getCycle(array('cycleid' => $cycleId));
  953. if (null === $cycle) {
  954. $this->getLogger()->warn("Tudu Cycle id: {$cycleId} is not exists");
  955. return ;
  956. }
  957. // 已经失效的周期设置
  958. if ($cycle->isValid == 0) {
  959. return ;
  960. }
  961. if (Dao_Td_Tudu_Cycle::END_TYPE_COUNT == $cycle->endType
  962. && $cycle->count >= $cycle->endCount) {
  963. $daoCycle->deleteCycle($cycle->cycleId);
  964. return ;
  965. }
  966. if (Dao_Td_Tudu_Cycle::END_TYPE_DATE == $cycle->endType
  967. && time() >= $cycle->endDate) {
  968. $daoCycle->deleteCycle($cycle->cycleId);
  969. return ;
  970. }
  971. $time = $daoCycle->getCycleTime($cycle, $tudu->startTime, $tudu->endTime);
  972. $recipients = array();
  973. $to = array();
  974. $fromUnId = null;
  975. $u = $daoUser->getUserByAddress($tudu->sender);
  976. if ($u) {
  977. $recipients[$u->uniqueId] = array(
  978. 'uniqueid' => $u->uniqueId,
  979. 'role' => 'from'
  980. );
  981. $fromUnId = $u->uniqueId;
  982. }
  983. if (!$acceptMode) {
  984. $accepters = $manager->getTuduAccepters($tudu->tuduId);
  985. foreach ($accepters as $a) {
  986. $recipients[$a['uniqueid']] = array(
  987. 'accepterinfo' => $a['accepterinfo'],
  988. 'uniqueid' => $a['uniqueid'],
  989. 'role' => Dao_Td_Tudu_Tudu::ROLE_ACCEPTER,
  990. 'tudustatus' => Dao_Td_Tudu_Tudu::STATUS_UNSTART,
  991. 'isforeign' => (int) $a['isforeign'],
  992. 'percent' => 0,
  993. 'authcode' => ((int) $a['isforeign'] && $tudu->isAuth) ? Oray_Function::randKeys(4) : null
  994. );
  995. if ($tudu->isAuth) {
  996. $recipients[$a['uniqueid']]['authcode'] = $a['authcode'];
  997. }
  998. $to[] = $a['accepterinfo'];
  999. }
  1000. }
  1001. // 公共周期任务图度数据
  1002. $params = $this->getCycleTuduParams($tudu, $cycle, $to, $fromUnId, $time);
  1003. // 抄送
  1004. if (!empty($tudu->cc)) {
  1005. $cc = array();
  1006. $sendCc = array();
  1007. foreach ($tudu->cc as $userName => $item) {
  1008. $cc[] = $userName . ' ' . $item[0];
  1009. }
  1010. $params['cc'] = implode("\n", $cc);
  1011. $sendCc = $this->formatRecipients($params['cc']);
  1012. $addressBook = Tudu_AddressBook::getInstance();
  1013. foreach ($sendCc as $key => $item) {
  1014. if (isset($item['groupid'])) {
  1015. if (0 === strpos($item['groupid'], 'XG')) {
  1016. $users = $addressBook->getGroupContacts($tudu->orgId, $fromUnId, $item['groupid']);
  1017. } else {
  1018. $users = $addressBook->getGroupUsers($tudu->orgId, $item['groupid']);
  1019. }
  1020. $recipients = array_merge($users, $recipients);
  1021. } else {
  1022. $user = $addressBook->searchUser($tudu->orgId, $item['email']);
  1023. if (null === $user) {
  1024. $user = $addressBook->searchContact($fromUnId, $item['email'], $item['truename']);
  1025. if (null === $user) {
  1026. $user = $addressBook->prepareContact($item['email'], $item['truename']);
  1027. }
  1028. }
  1029. if (!isset($recipients[$user['uniqueid']])) {
  1030. $recipients[$user['uniqueid']] = $user;
  1031. }
  1032. }
  1033. }
  1034. }
  1035. // 密送
  1036. if (!empty($tudu->bcc)) {
  1037. $bcc = array();
  1038. $sendBcc = array();
  1039. foreach ($tudu->bcc as $userName => $item) {
  1040. $bcc[] = $userName . ' ' . $item[0];
  1041. }
  1042. $params['bcc'] = implode("\n", $bcc);
  1043. $sendBcc = $this->formatRecipients($params['bcc']);
  1044. $addressBook = Tudu_AddressBook::getInstance();
  1045. foreach ($sendBcc as $key => $item) {
  1046. if (isset($item['groupid'])) {
  1047. if (0 === strpos($item['groupid'], 'XG')) {
  1048. $users = $addressBook->getGroupContacts($tudu->orgId, $fromUnId, $item['groupid']);
  1049. } else {
  1050. $users = $addressBook->getGroupUsers($tudu->orgId, $item['groupid']);
  1051. }
  1052. $recipients = array_merge($users, $recipients);
  1053. } else {
  1054. $user = $addressBook->searchUser($tudu->orgId, $item['email']);
  1055. if (null === $user) {
  1056. $user = $addressBook->searchContact($fromUnId, $item['email'], $item['truename']);
  1057. if (null === $user) {
  1058. $user = $addressBook->prepareContact($item['email'], $item['truename']);
  1059. }
  1060. }
  1061. if (!isset($recipients[$user['uniqueid']])) {
  1062. $recipients[$user['uniqueid']] = $user;
  1063. }
  1064. }
  1065. }
  1066. }
  1067. // 会议数据
  1068. if ($tudu->type == 'meeting') {
  1069. $daoMeeting = Tudu_Dao_Manager::getDao('Dao_Td_Tudu_Meeting', Tudu_Dao_Manager::DB_TS);
  1070. $meeting = $daoMeeting->getMeeting(array('tuduid' => $tudu->tuduId));
  1071. if ($meeting) {
  1072. $params['meeting'] = array(
  1073. 'notifytype' => $meeting->notifyType,
  1074. 'location' => $meeting->location,
  1075. 'isallday' => $meeting->isAllday
  1076. );
  1077. $params['meeting']['notifytime'] = Dao_Td_Tudu_Meeting::calNotifyTime($params['starttime'], $meeting->notifyType);
  1078. }
  1079. }
  1080. // 保留周期任务的附件
  1081. if ($cycle->isKeepAttach) {
  1082. $daoAttach = Tudu_Dao_Manager::getDao('Dao_Td_Attachment_File', Tudu_Dao_Manager::DB_TS);
  1083. $attaches = $daoAttach->getFiles(array('tuduid' => $tudu->tuduId, 'postid' => $tudu->postId))->toArray();
  1084. $attachNum = 0;
  1085. foreach ($attaches as $attach) {
  1086. if ($attach['isattach']) {
  1087. $params['attachment'][] = $attach['fileid'];
  1088. } else {
  1089. $params['file'][] = $attach['fielid'];
  1090. }
  1091. }
  1092. }
  1093. $stepId = $params['stepid'];
  1094. $tudu = new Tudu_Tudu_Storage_Tudu($params);
  1095. $storage = Tudu_Tudu_Storage::getInstance(Tudu_Dao_Manager::getDb(Tudu_Dao_Manager::DB_TS));
  1096. $deliver = Tudu_Tudu_Deliver::getInstance();
  1097. $tuduId = $storage->createTudu($tudu);
  1098. if (!$tuduId) {
  1099. $this->getLogger()->warn("Create Cycle Tudu failed id:{$tuduId}");
  1100. return ;
  1101. }
  1102. if ($params['type'] == 'task' && $tuduId) {
  1103. $daoFlow = Tudu_Dao_Manager::getDao('Dao_Td_Tudu_Flow', Tudu_Dao_Manager::DB_TS);
  1104. $flow = $daoFlow->getFlow(array('tuduid' => $fromTuduId));
  1105. $steps = $flow->steps;
  1106. $step = reset($steps);
  1107. $modelFlow = new Model_Tudu_Extension_Flow(array('orgid' => $tudu->orgId, 'tuduid' => $tuduId));
  1108. /*$step = $daoStep->getStep(array('tuduid' => $fromTuduId, 'prevstepid' => '^head'));
  1109. $orderNum = 1;*/
  1110. $prevStepId = '^head';
  1111. $addressBook = Tudu_AddressBook::getInstance();
  1112. // 认领
  1113. if ($step && $step['type'] == Dao_Td_Tudu_Step::TYPE_CLAIM) {
  1114. $modelFlow->addStep(array(
  1115. 'stepid' => $step['stepid'],
  1116. 'prev' => $step['prev'],
  1117. 'next' => '^end',
  1118. 'type' => $step['type']
  1119. ));
  1120. $acceptMode = true;
  1121. $to = array();
  1122. foreach ($step['section'] as $idx => $sec) {
  1123. $section = array();
  1124. foreach ($sec as $user) {
  1125. $section[] = array(
  1126. 'uniqueid' => $user['uniqueid'],
  1127. 'username' => $user['username'],
  1128. 'truename' => $user['truename']
  1129. );
  1130. if ($idx == 0) {
  1131. $to[] = $user['username'] . ' '. $user['truename'];
  1132. $recipient = array(
  1133. 'uniqueid' => $user['uniqueid'],
  1134. 'userinfo' => $user['username'] . ' '. $user['truename'],
  1135. 'role' => Dao_Td_Tudu_Tudu::ROLE_ACCEPTER,
  1136. 'tudustatus' => Dao_Td_Tudu_Tudu::STATUS_UNSTART,
  1137. 'percent' => 0
  1138. );
  1139. $u = $addressBook->searchUser($fromUnId, $user['username']);
  1140. if (!$u) {
  1141. $recipient['isforeign'] = 1;
  1142. if ($isAuth) {
  1143. $recipient['auth'] = Oray_Function::randKeys(4);
  1144. }
  1145. }
  1146. $recipients[$recipient['uniqueid']] = $recipient;
  1147. }
  1148. }
  1149. $modelFlow->addStepSection($step['stepid'], $sec);
  1150. }
  1151. $modelFlow->stepNum = 1;
  1152. $modelFlow->flowTo($step['stepid']);
  1153. $daoFlow->createFlow($modelFlow->toArray());
  1154. // 更新to字段
  1155. $manager->updateTudu($tuduId, array(
  1156. 'to' => implode("\n", $to),
  1157. 'acceptmode' => 1,
  1158. 'accepttime' => null
  1159. ));
  1160. } else {
  1161. // 审批
  1162. $nextId = $step['next'];
  1163. $modelFlow->addStep(array(
  1164. 'stepid' => $step['stepid'],
  1165. 'prev' => $step['prev'],
  1166. 'next' => $step['next'],
  1167. 'type' => $step['type']
  1168. ));
  1169. foreach ($step['section'] as $idx => $sec) {
  1170. $section = array();
  1171. foreach ($sec as $user) {
  1172. $section[] = array(
  1173. 'uniqueid' => $user['uniqueid'],
  1174. 'username' => $user['username'],
  1175. 'truename' => $user['truename']
  1176. );
  1177. if ($idx == 0) {
  1178. $to[] = $user['username'] . ' '. $user['truename'];
  1179. $recipient = array(
  1180. 'uniqueid' => $user['uniqueid'],
  1181. 'userinfo' => $user['username'] . ' '. $user['truename'],
  1182. 'role' => isset($recipients[$user['uniqueid']]) ? $recipients[$user['uniqueid']]['role'] : null,
  1183. 'isreview' => true,
  1184. 'tudustatus' => Dao_Td_Tudu_Tudu::STATUS_UNSTART
  1185. );
  1186. $recipients[$recipient['uniqueid']] = $recipient;
  1187. }
  1188. }
  1189. $modelFlow->addStepSection($step['stepid'], $sec);
  1190. }
  1191. if (isset($flow->steps[$nextId])) {
  1192. $next = $flow->steps[$nextId];
  1193. $modelFlow->addStep(array(
  1194. 'stepid' => $next['stepid'],
  1195. 'prev' => $next['prev'],
  1196. 'next' => '^end',
  1197. 'type' => $next['type']
  1198. ));
  1199. foreach ($next['section'] as $idx => $sec) {
  1200. $section = array();
  1201. foreach ($sec as $user) {
  1202. $section[] = array(
  1203. 'uniqueid' => $user['uniqueid'],
  1204. 'username' => $user['username'],
  1205. 'truename' => $user['truename']
  1206. );
  1207. }
  1208. $modelFlow->addStepSection($next['stepid'], $sec);
  1209. }
  1210. }
  1211. $modelFlow->stepNum = count($modelFlow->steps);
  1212. $modelFlow->flowTo($step['stepid']);
  1213. $daoFlow->createFlow($modelFlow->toArray());
  1214. }
  1215. }
  1216. $sendParams = array();
  1217. if ($tudu->type == 'meeting') {
  1218. $sendParams['meeting'] = true;
  1219. }
  1220. if (empty($reviewer)) {
  1221. $ret = $deliver->sendTudu($tudu, $recipients, $sendParams);
  1222. if (!$ret) {
  1223. $this->getLogger()->warn("Send Tudu failed id:{$tuduId}");
  1224. return ;
  1225. }
  1226. if (!$acceptMode) {
  1227. foreach ($recipients as $unId => $recipient) {
  1228. if (isset($recipient['role']) && $recipient['role'] == Dao_Td_Tudu_Tudu::ROLE_ACCEPTER) {
  1229. $manager->acceptTudu($tuduId, $unId, null);
  1230. }
  1231. }
  1232. }
  1233. } else {
  1234. $rev = array_shift($reviewer);
  1235. $ret = $deliver->sendTudu($tudu, array(
  1236. $rev['uniqueid'] => array('tuduid' => $tuduId, 'uniqueid' => $rev['uniqueid']),
  1237. $fromUnId => array('tuduid' => $tuduId, 'uniqueid' => $fromUnId)
  1238. ), null);
  1239. if (!$ret) {
  1240. $this->getLogger()->warn("Send Tudu failed id:{$tuduId}");
  1241. return ;
  1242. }
  1243. $manager->addLabel($tuduId, $rev['uniqueid'], '^e');
  1244. }
  1245. // 发起人的
  1246. if (null !== $fromUnId) {
  1247. $manager->addLabel($tuduId, $fromUnId, '^f');
  1248. $manager->addLabel($tuduId, $fromUnId, '^i');
  1249. }
  1250. $daoCycle->increment($cycle->cycleId);
  1251. // 收发规则过滤
  1252. $data = implode(' ', array(
  1253. 'tudu',
  1254. 'filter',
  1255. '',
  1256. http_build_query(array(
  1257. 'tsid' => $tsId,
  1258. 'tuduid' => $tuduId
  1259. ))
  1260. ));
  1261. $this->_httpsqs->put($data, $this->_options['httpsqs']['names']['tudu']);
  1262. // 外发请求
  1263. $data = implode(' ', array(
  1264. 'send',
  1265. 'tudu',
  1266. '',
  1267. http_build_query(array(
  1268. 'tsid' => $tsId,
  1269. 'tuduid' => $tuduId,
  1270. 'uniqueid' => $fromUnId,
  1271. 'to' => ''
  1272. ))
  1273. ));
  1274. $this->_httpsqs->put($data, $this->_options['httpsqs']['names']['send']);
  1275. $this->getLogger()->debug("Tudu id:{$tuduId} done");
  1276. }
  1277. /**
  1278. * 执行图度规则过滤
  1279. *
  1280. * 遍历所有接收人所有可用规则,并执行过滤
  1281. * @param $params
  1282. */
  1283. public function filterTudu($params)
  1284. {
  1285. if (empty($params['tuduid'])
  1286. || empty($params['tsid']))
  1287. {
  1288. return ;
  1289. }
  1290. $tuduId = $params['tuduid'];
  1291. $manager = Tudu_Tudu_Manager::getInstance(Tudu_Dao_Manager::getDb(Tudu_Dao_Manager::DB_TS));
  1292. /** @var $daoRule Dao_Td_Rule_Rule */
  1293. $daoRule = Tudu_Dao_Manager::getDao('Dao_Td_Rule_Rule', Tudu_Dao_Manager::DB_TS);
  1294. $users = $manager->getTuduUsers($tuduId);
  1295. if (!$users) {
  1296. $this->getLogger()->warn("Tudu id:{$tuduId} Users are not exists");
  1297. return ;
  1298. }
  1299. $tudu = $manager->getTuduById($tuduId, $users[0]['uniqueid']);
  1300. if (null === $tudu) {
  1301. $this->getLogger()->warn("Tudu id: {$tuduId} is not exists");
  1302. return ;
  1303. }
  1304. $tudu = $tudu->toArray();
  1305. $expire = 3600*24;//定义Memcache过期时间: 一天
  1306. // 获取接收用户规则过滤
  1307. foreach ($users as $user) {
  1308. $unId = $user['uniqueid'];
  1309. $rules = $this->_memcache->loadCache(array($daoRule, 'getRulesByUniqueId'), array($unId, array('isvalid' => true)), $expire);
  1310. if ($rules->count() <= 0) {
  1311. continue ;
  1312. }
  1313. foreach ($rules as $rule) {
  1314. $filters = $rule->getFilters();
  1315. $filterCount = $filters->count();
  1316. $matchCount = 0;
  1317. if ($filterCount <= 0) {
  1318. continue ;
  1319. }
  1320. foreach ($filters as $filter) {
  1321. $contain = false;
  1322. switch ($filter->what) {
  1323. // 发起人
  1324. case 'from':
  1325. if (is_array($filter->value)) {
  1326. foreach ($filter->value as $item) {
  1327. $item = str_replace(array('oray.com', 'tudu.com'), array('oray', ''), $item);
  1328. if ($item == $tudu['from'][3]) {
  1329. $contain = true;
  1330. break;
  1331. }
  1332. }
  1333. }
  1334. break;
  1335. // 接收人,抄送人
  1336. case 'to':
  1337. case 'cc':
  1338. if (is_array($filter->value)) {
  1339. $count = 0;
  1340. $match = 0;
  1341. foreach ($filter->value as $item) {
  1342. $count++;
  1343. $item = str_replace(array('oray.com', 'tudu.com'), array('oray', ''), $item);
  1344. if (isset($tudu[$filter->what][$item])) {
  1345. $match ++;
  1346. }
  1347. }
  1348. if ($count == $match) {
  1349. $contain = true;
  1350. }
  1351. }
  1352. break;
  1353. case 'subject':
  1354. $contain = false !== strpos($tudu['subject'], $filter->value);
  1355. break;
  1356. }
  1357. if (($filter->type == 'contain' && $contain) || ($filter->type == 'exclusive' && !$contain)) {
  1358. $matchCount++;
  1359. }
  1360. }
  1361. // 匹配过滤条件,执行规则操作
  1362. if ($matchCount == $filterCount) {
  1363. // 标签
  1364. if ($rule->operation == 'label') {
  1365. $manager->addLabel($tuduId, $unId, $rule->value);
  1366. // 忽略
  1367. } elseif ($rule->operation == 'ignore') {
  1368. $manager->deleteLabel($tuduId, $unId, '^i');
  1369. $manager->addLabel($tuduId, $unId, '^g');
  1370. // 星标
  1371. } elseif ($rule->operation == 'starred') {
  1372. $manager->addLabel($tuduId, $unId, '^t');
  1373. }
  1374. // 是否需要邮件提醒
  1375. if (!empty($rule->mailRemind)) {
  1376. $mailRemind = $rule->mailRemind;
  1377. // 邮件提醒可用且图度在指定的板块的
  1378. if ($mailRemind['isvalid'] // 是否开启邮件提醒功能
  1379. && !empty($mailRemind['boards']) // 有设置板块
  1380. && !empty($mailRemind['mailbox']) // 有设置接收的邮箱
  1381. && is_array($mailRemind['boards']) // 指定板块必须是数组
  1382. && in_array($tudu['boardid'], $mailRemind['boards'])) // 指定板块下的图度才会有邮件提醒
  1383. {
  1384. $emails = array();
  1385. foreach ($mailRemind['mailbox'] as $email) {
  1386. // 必须是邮箱
  1387. if (Oray_Function::isEmail($email)) {
  1388. $emails[] = $email;
  1389. }
  1390. }
  1391. if (!empty($emails)) {
  1392. $remind = array(
  1393. 'tuduid' => $tudu['tuduid'],
  1394. 'tsid' => $params['tsid'],
  1395. 'emails' => $emails,
  1396. 'subject' => $tudu['subject'],
  1397. 'sender' => $tudu['from'][0],
  1398. 'lastupdate' => date('Y-m-d H:i:s', $tudu['lastposttime']),
  1399. 'content' => mb_substr(strip_tags($tudu['content']), 0, 20, 'utf-8'),
  1400. 'type' => $this->_typeNames[$tudu['type']],
  1401. 'url' => 'http://' . $tudu['orgid'] . '.tudu.com/tudu/view?tid=' . $tudu['tuduid']
  1402. );
  1403. $this->getLogger()->warn("Send Email notify to:" . implode(',', $emails));
  1404. // 发送邮件提醒请求
  1405. $data = implode(' ', array(
  1406. 'send',
  1407. 'email',
  1408. '',
  1409. http_build_query($remind)
  1410. ));
  1411. $this->_httpsqs->put($data, $this->_options['httpsqs']['names']['send']);
  1412. }
  1413. }
  1414. }
  1415. }
  1416. }
  1417. }
  1418. $this->getLogger()->debug("Tudu id:{$tuduId} done");
  1419. }
  1420. /**
  1421. * 更新图度规则
  1422. * @param $params
  1423. */
  1424. public function updateRules($params)
  1425. {
  1426. if (empty($params['ruleid'])
  1427. || empty($params['tsid']))
  1428. {
  1429. return ;
  1430. }
  1431. $ruleId = $params['ruleid'];
  1432. $manager = Tudu_Tudu_Manager::getInstance(Tudu_Dao_Manager::getDb(Tudu_Dao_Manager::DB_TS));
  1433. /** @var $daoRule Dao_Td_Rule_Rule */
  1434. $daoRule = Tudu_Dao_Manager::getDao('Dao_Td_Rule_Rule', Tudu_Dao_Manager::DB_TS);
  1435. $rule = $daoRule->getRuleById($ruleId);
  1436. if ($rule == null) {
  1437. $this->getLogger()->warn("Tudu Rule id: {$ruleId} is not exists");
  1438. return ;
  1439. }
  1440. $uniqueId = $rule->uniqueId;
  1441. $filters = $rule->getFilters()->toArray();
  1442. if (count($filters) <= 0) {
  1443. $this->getLogger()->warn("Tudu Rule->getFilters() null ruleid: {$ruleId} is not exists");
  1444. return ;
  1445. }
  1446. $subject = null;
  1447. $subjectType = ' LIKE ';
  1448. foreach ($filters as $key => $filter) {
  1449. if ($filter['what'] == 'subject') {
  1450. $subject = $filter['value'];
  1451. if ($filter['type'] != 'contain') {
  1452. $subjectType = ' NOT LIKE ';
  1453. }
  1454. unset($filters[$key]);
  1455. break;
  1456. }
  1457. }
  1458. $tsdb = Tudu_Dao_Manager::getDb(Tudu_Dao_Manager::DB_TS);
  1459. // 过滤现有tudu
  1460. if ($rule->isValid) {
  1461. $sql = 'SELECT t.tudu_id AS tuduid, `from`, `to`, `cc`, `subject` FROM td_tudu t '
  1462. . 'LEFT JOIN td_tudu_user tu ON t.tudu_id = tu.tudu_id '
  1463. . 'WHERE tu.unique_id = ' . $tsdb->quote($uniqueId) . ' AND tu.labels IS NOT NULL ';
  1464. if ($subject) {
  1465. $sql .= ' AND t.subject ' . $subjectType . $tsdb->quote('%' . $subject . '%');
  1466. }
  1467. $query = $tsdb->query($sql);
  1468. while ($row = $query->fetch()) {
  1469. $match = false;
  1470. if (count($filters)) {
  1471. $filterCount = count($filters);
  1472. $matchCount = 0;
  1473. // 检查发送人,接收人,抄送人
  1474. foreach ($filters as $filter) {
  1475. $contain = false;
  1476. if (in_array($filter['what'], array('from', 'to', 'cc'))) {
  1477. if (is_array($filter['value'])) {
  1478. $vc = count($filter['value']);
  1479. $mc = 0;
  1480. $arr = explode("\n", $row[$filter['what']]);
  1481. $users = array();
  1482. foreach ($arr as $item) {
  1483. $item = explode(' ', $item);
  1484. $users[$item[0]] = $item[1];
  1485. }
  1486. foreach ($filter['value'] as $value) {
  1487. $value = str_replace(array('oray.com', 'tudu.com'), array('oray', ''), $value);
  1488. if (isset($users[$value])) {
  1489. if ($filter['what'] == 'from' && $filter['type'] == 'contain') {
  1490. $matchCount ++;
  1491. continue 2;
  1492. }
  1493. $mc ++;
  1494. }
  1495. }
  1496. if ($vc == $mc) {
  1497. $contain = true;
  1498. }
  1499. }
  1500. } elseif ($filter['what'] == 'subject') {
  1501. $contain = false !== strpos($tudu['subject'], $filter->value);
  1502. }
  1503. if (($contain && $filter['type'] == 'contain') ||(!$contain && $filter['type'] == 'exclusive')) {
  1504. $matchCount ++;
  1505. }
  1506. }
  1507. if ($filterCount == $matchCount && $matchCount > 0) {
  1508. $match = true;
  1509. }
  1510. } else {
  1511. $match = true;
  1512. }
  1513. // 匹配过滤条件,执行规则操作
  1514. if ($match) {
  1515. // 标签
  1516. if ($rule->operation == 'label') {
  1517. $manager->addLabel($row['tuduid'], $uniqueId, $rule->value);
  1518. // 忽略
  1519. } elseif ($rule->operation == 'ignore') {
  1520. $manager->deleteLabel($row['tuduid'], $uniqueId, '^i');
  1521. $manager->addLabel($row['tuduid'], $uniqueId, '^g');
  1522. // 星标
  1523. } elseif ($rule->operation == 'starred') {
  1524. $manager->addLabel($row['tuduid'], $uniqueId, '^t');
  1525. }
  1526. }
  1527. }
  1528. }
  1529. $this->getLogger()->debug("Rule id:{$ruleId} done");
  1530. }
  1531. /**
  1532. * 发送图度提醒
  1533. *
  1534. * @param $tudu
  1535. * @param $server
  1536. * @param $notifyTo
  1537. */
  1538. public function sendTuduNotify($action, $tudu, $from, $server, $notifyTo)
  1539. {
  1540. if (!$tudu) {
  1541. return ;
  1542. }
  1543. $disception = htmlspecialchars(str_replace('%', '%%', mb_substr(preg_replace('/<[^>]+>/', '', $tudu->content), 0, 100, 'UTF-8')));
  1544. $subject = htmlspecialchars(htmlspecialchars($tudu->subject)); // 转义两次,talk客户端会有一次转换
  1545. $sendtime = date('Y-m-d H:i:s', $tudu->createTime);
  1546. $content = <<<HTML
  1547. <strong>您刚收到一个新的{$this->_typeNames[$tudu->type]}</strong><br />
  1548. <a href="http://{$server}/frame#m=view&tid={$tudu->tuduId}&page=1" target="_blank" _tid="{$tudu->tuduId}">{$subject}</a><br />
  1549. 发起人{$tudu->from[0]}<br />
  1550. 发送日期{$sendtime}<br />
  1551. $disception
  1552. HTML;
  1553. $count = @count($notifyTo);
  1554. if ($count >= 20) {
  1555. $to = array(); $counter = 0;
  1556. do {
  1557. $arr[] = array_shift($notifyTo);
  1558. $counter ++ ;
  1559. if ($counter >= 20 || count($notifyTo) == 0) {
  1560. $to[] = $arr;
  1561. $arr = array();
  1562. $counter = 0;
  1563. }
  1564. } while (count($notifyTo) > 0);
  1565. } else {
  1566. $to = array($notifyTo);
  1567. }
  1568. foreach ($to as $item) {
  1569. // 发送talk提醒
  1570. $this->_httpsqs->put(implode(' ', array(
  1571. 'tudu',
  1572. 'create',
  1573. '',
  1574. http_build_query(array(
  1575. 'tuduid' => $tudu->tuduId,
  1576. 'from' => $from,
  1577. 'to' => implode(',', $item),
  1578. 'content' => $content
  1579. ))
  1580. )), $this->_options['httpsqs']['names']['im']);
  1581. }
  1582. }
  1583. /**
  1584. * 发送回复提醒
  1585. */
  1586. public function sendPostNotify($tudu, $post, $from, $server, $notifyTo)
  1587. {
  1588. $description = $content = htmlspecialchars($this->getPostDescription($post));
  1589. $content = <<<HTML
  1590. <strong>您刚收到一个新的回复</strong><br />
  1591. <a href="http://{$server}/frame#m=view&tid=%s&page=1" target="_blank" _tid="{$tudu->tuduId}">%s</a><br />
  1592. 发起人{$post->poster}<br />
  1593. 更新日期%s<br />
  1594. $description
  1595. HTML;
  1596. $count = @count($notifyTo);
  1597. if ($count >= 20) {
  1598. $to = array(); $counter = 0;
  1599. do {
  1600. $arr[] = array_shift($notifyTo);
  1601. $counter ++ ;
  1602. if ($counter >= 20 || count($notifyTo) == 0) {
  1603. $to[] = $arr;
  1604. $arr = array();
  1605. $counter = 0;
  1606. }
  1607. } while (count($notifyTo) > 0);
  1608. } else {
  1609. $to = array($notifyTo);
  1610. }
  1611. foreach ($to as $item) {
  1612. $data = implode(' ', array(
  1613. 'tudu',
  1614. 'reply',
  1615. '',
  1616. http_build_query(array(
  1617. 'tuduid' => $tudu->tuduId,
  1618. 'from' => $from,
  1619. 'to' => implode(',', $item),
  1620. 'content' => sprintf($content, $tudu->tuduId, htmlspecialchars(htmlspecialchars($tudu->subject)), date('Y-m-d H:i:s', time()))
  1621. ))
  1622. ));
  1623. $this->_httpsqs->put($data, $this->_options['httpsqs']['names']['im']);
  1624. }
  1625. }
  1626. /**
  1627. * 发送审批回复提醒
  1628. */
  1629. public function sendReviewPostNotify($tudu, $agree, $from, $server, $notifyTo)
  1630. {
  1631. if (!$tudu) {
  1632. return ;
  1633. }
  1634. $content = $agree ? '已经同意本次申请。' : '不同意本次申请;<br />请申请者修改后再重新提交审批。';
  1635. $subject = htmlspecialchars(htmlspecialchars($tudu->subject));
  1636. $sendtime = date('Y-m-d H:i:s', $tudu->createTime);
  1637. $tpl = <<<HTML
  1638. <strong>您刚收到一个新的回复</strong><br />
  1639. <a href="http://{$server}/frame#m=view&tid={$tudu->tuduId}&page=1" target="_blank" _tid="{$tudu->tuduId}">{$subject}</a><br />
  1640. 发起人{$tudu->from[0]}<br />
  1641. 发送日期{$sendtime}<br />
  1642. $content
  1643. HTML;
  1644. // 发送talk提醒
  1645. $count = @count($notifyTo);
  1646. if ($count >= 20) {
  1647. $to = array(); $counter = 0;
  1648. do {
  1649. $arr[] = array_shift($notifyTo);
  1650. $counter ++ ;
  1651. if ($counter >= 20 || count($notifyTo) == 0) {
  1652. $to[] = $arr;
  1653. $arr = array();
  1654. $counter = 0;
  1655. }
  1656. } while (count($notifyTo) > 0);
  1657. } else {
  1658. $to = array($notifyTo);
  1659. }
  1660. foreach ($to as $item) {
  1661. // 发送talk提醒
  1662. $data = implode(' ', array(
  1663. 'tudu',
  1664. 'reply',
  1665. '',
  1666. http_build_query(array(
  1667. 'tuduid' => $tudu->tuduId,
  1668. 'from' => $from,
  1669. 'to' => implode(',', $item),
  1670. 'content' => $tpl
  1671. ))
  1672. ));
  1673. $this->_httpsqs->put($data, $this->_options['httpsqs']['names']['im']);
  1674. }
  1675. }
  1676. /**
  1677. * 回复描述
  1678. *
  1679. * @param array $post
  1680. * @return string
  1681. */
  1682. public function getPostDescription($post)
  1683. {
  1684. return mb_substr(str_replace('%', '%%', preg_replace('/<[^>]+>/', '', $post->content)), 0, 100, 'UTF-8');
  1685. }
  1686. /**
  1687. * 周期任务/会议
  1688. * 图度数据
  1689. *
  1690. * @param $tudu
  1691. * @param $fromUnId
  1692. */
  1693. public function getCycleTuduParams($tudu, $cycle, $to, $fromUnId, $time)
  1694. {
  1695. // 基本参数
  1696. return array(
  1697. 'orgid' => $tudu->orgId,
  1698. 'boardid' => $tudu->boardId,
  1699. 'classid' => $tudu->classId,
  1700. 'tuduid' => Dao_Td_Tudu_Tudu::getTuduId(),
  1701. 'special' => Dao_Td_Tudu_Tudu::SPECIAL_CYCLE,
  1702. 'cycleid' => $cycle->cycleId,
  1703. 'uniqueid' => $fromUnId,
  1704. 'email' => $tudu->sender,
  1705. 'type' => $tudu->type,
  1706. 'subject' => $tudu->subject,
  1707. 'from' => $tudu->from[3] . ' ' . $tudu->from[0],
  1708. 'to' => implode("\n", $to),
  1709. 'priority' => $tudu->priority,
  1710. 'privacy' => $tudu->privacy,
  1711. 'status' => Dao_Td_Tudu_Tudu::STATUS_UNSTART,
  1712. 'content' => $tudu->content,
  1713. 'poster' => $tudu->from[0],
  1714. 'posterinfo' => $tudu->posterInfo,
  1715. 'lastposter' => $tudu->from[0],
  1716. 'lastposttime' => time(),
  1717. 'starttime' => $time[0],
  1718. 'endtime' => $time[1],
  1719. 'createtime' => time(),
  1720. 'password' => $tudu->password,
  1721. 'isauth' => $tudu->isAuth,
  1722. 'cyclenum' => $tudu->cycleNum + 1,
  1723. 'stepid' => Dao_Td_Tudu_Step::getStepId(),
  1724. 'stepnum' => 1,
  1725. 'issend' => 1,
  1726. 'acceptmode' => $tudu->acceptMode,
  1727. 'needconfirm' => $tudu->needConfirm,
  1728. 'attachment' => array(),
  1729. 'file' => array()
  1730. );
  1731. }
  1732. /**
  1733. * 格式化接收人格式
  1734. *
  1735. * @param string $recipients
  1736. */
  1737. public function formatRecipients($recipients)
  1738. {
  1739. if (is_array($recipients)) {
  1740. return $recipients;
  1741. }
  1742. $arr = explode("\n", $recipients);
  1743. $ret = array();
  1744. foreach ($arr as $item) {
  1745. if (!trim($item)) {
  1746. continue ;
  1747. }
  1748. list($key, $name) = explode(' ', $item, 2);
  1749. if (false !== strpos($key, '@')) {
  1750. $ret[$key] = array('email' => $key, 'truename' => $name);
  1751. } else {
  1752. $ret[$key] = array('groupid' => $key, 'truename' => $name);
  1753. }
  1754. }
  1755. return $ret;
  1756. }
  1757. }