zentaobiz.class.php 66 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481
  1. <?php
  2. helper::import(dirname(__FILE__) . DS . 'bizext.class.php');
  3. class zentaobizUpgrade extends bizextUpgrade
  4. {
  5. /**
  6. * Adjust feedback view data.
  7. *
  8. * @access public
  9. * @return bool
  10. */
  11. public function adjustFeedbackViewData()
  12. {
  13. $this->saveLogs('Run Method ' . __FUNCTION__);
  14. $desc = $this->dao->query('DESC ' . TABLE_FEEDBACKVIEW)->fetchAll();
  15. $this->saveLogs($this->dao->get());
  16. $hasProductsField = false;
  17. foreach($desc as $field)
  18. {
  19. if($field->Field == 'products') $hasProductsField = true;
  20. }
  21. if(!$hasProductsField) return true;
  22. $feedbackView = $this->dao->select('account, products')->from(TABLE_FEEDBACKVIEW)->fetchPairs();
  23. $this->dao->delete()->from(TABLE_FEEDBACKVIEW)->exec();
  24. $this->saveLogs($this->dao->get());
  25. foreach($feedbackView as $account => $products)
  26. {
  27. if(empty($products)) continue;
  28. foreach(explode(',', $products) as $productID)
  29. {
  30. $productID = trim($productID);
  31. if(empty($productID)) continue;
  32. $view = new stdclass();
  33. $view->account = $account;
  34. $view->product = $productID;
  35. $this->dao->delete()->from(TABLE_FEEDBACKVIEW)->where('account')->eq($account)->andWhere('product')->eq($productID)->exec();
  36. $this->dao->insert(TABLE_FEEDBACKVIEW)->data($view)->exec();
  37. $this->saveLogs($this->dao->get());
  38. }
  39. }
  40. $this->dao->exec("ALTER TABLE " . TABLE_FEEDBACKVIEW . " DROP `products`");
  41. $this->saveLogs($this->dao->get());
  42. return true;
  43. }
  44. /**
  45. * Import zentao module for workflow.
  46. *
  47. * @param string $vision
  48. * @access public
  49. * @return bool
  50. */
  51. public function importBuildinModules($vision = 'all')
  52. {
  53. $this->saveLogs('Run Method ' . __FUNCTION__);
  54. $this->loadModel('workflow');
  55. $this->loadModel('workflowaction');
  56. $this->loadModel('workflowfield');
  57. $modules = $this->config->workflow->buildin->modules;
  58. $visions = $this->config->workflow->buildin->visions;
  59. $actions = $this->config->workflowaction->buildin->actions;
  60. $actionTypes = $this->config->workflowaction->buildin->types;
  61. $actionMethods = $this->config->workflowaction->buildin->methods;
  62. $actionOpens = $this->config->workflowaction->buildin->opens;
  63. $actionLayouts = $this->config->workflowaction->buildin->layouts;
  64. $actionPositions = $this->config->workflowaction->buildin->positions;
  65. $actionShows = $this->config->workflowaction->buildin->shows;
  66. $fields = $this->config->workflowfield->buildin->fields;
  67. $account = isset($this->app->user->account) ? $this->app->user->account : 'admin';
  68. $now = helper::now();
  69. $this->dao->begin();
  70. /* Insert buildin modules to TABLE_WORKFLOW. */
  71. $data = new stdclass();
  72. $data->buildin = 1;
  73. $data->createdBy = $account;
  74. $data->createdDate = $now;
  75. $data->status = 'normal';
  76. foreach($modules as $app => $appModules)
  77. {
  78. $data->app = $app;
  79. foreach($appModules as $module => $options)
  80. {
  81. $this->app->loadLang($module);
  82. $data->vision = 'rnd';
  83. $data->module = $module;
  84. $data->name = isset($this->lang->$module->common) ? $this->lang->$module->common : $module;
  85. $data->table = str_replace('`', '', zget($options, 'table', ''));
  86. $data->navigator = zget($options, 'navigator', 'secondary');
  87. if(!empty($visions[$module])) $data->vision = $visions[$module];
  88. if($module == 'execution') $data->name = $this->lang->workflow->execution;
  89. if($module == 'story') $data->name = $this->lang->SRCommon;
  90. if($module == 'epic') $data->name = $this->lang->ERCommon;
  91. if($module == 'requirement') $data->name = $this->lang->URCommon;
  92. if($vision != 'all' && $vision != $data->vision) continue;
  93. $this->dao->delete()->from(TABLE_WORKFLOW)->where('app')->eq($app)->andWhere('module')->eq($module)->andWhere('vision')->eq($data->vision)->exec();
  94. $this->dao->insert(TABLE_WORKFLOW)->data($data)->exec();
  95. if(dao::isError())
  96. {
  97. $this->dao->rollBack();
  98. return false;
  99. }
  100. }
  101. }
  102. /* Insert actions of buildin modules to TABLE_WORKFLOWACTION. */
  103. $data = new stdclass();
  104. $data->buildin = 1;
  105. $data->role = 'buildin';
  106. $data->extensionType = 'none';
  107. $data->createdBy = $account;
  108. $data->createdDate = $now;
  109. foreach($actions as $module => $moduleActions)
  110. {
  111. $data->module = $module;
  112. foreach($moduleActions as $action)
  113. {
  114. $data->action = $action;
  115. /* Use default action name if not set flow action name. */
  116. $name = '';
  117. if(isset($this->lang->$module->$action)) $name = $this->lang->$module->$action;
  118. if($data->module == 'execution' && $action == 'all') $name = $this->lang->execution->allExecutionAB;
  119. if(empty($name) && in_array($action, array_keys($this->config->flowAction)))
  120. {
  121. $methodName = $this->config->flowAction[$action];
  122. if(isset($this->lang->$module->$methodName)) $name = $this->lang->$module->$methodName;
  123. }
  124. if(empty($name) && isset($this->lang->workflowaction->default->actions[$action])) $name = $this->lang->workflowaction->default->actions[$action];
  125. if(empty($name)) $name = $action;
  126. $data->name = $name;
  127. $data->method = $data->action;
  128. $data->open = 'normal';
  129. $data->layout = 'normal';
  130. $data->type = 'single';
  131. $data->position = 'browseandview';
  132. $data->show = 'direct';
  133. $data->vision = 'rnd';
  134. if(isset($actionMethods[$module][$action])) $data->method = $actionMethods[$module][$action];
  135. if(isset($actionOpens[$module][$action])) $data->open = $actionOpens[$module][$action];
  136. if(isset($actionLayouts[$module][$action])) $data->layout = $actionLayouts[$module][$action];
  137. if(isset($actionTypes[$module][$action])) $data->type = $actionTypes[$module][$action];
  138. if(isset($actionPositions[$module][$action])) $data->position = $actionPositions[$module][$action];
  139. if(isset($actionShows[$module][$action])) $data->show = $actionShows[$module][$action];
  140. if(!empty($visions[$module])) $data->vision = $visions[$module];
  141. if($vision != 'all' && $vision != $data->vision) continue;
  142. $this->dao->delete()->from(TABLE_WORKFLOWACTION)->where('module')->eq($module)->andWhere('action')->eq($action)->andWhere('vision')->eq($data->vision)->exec();
  143. $this->dao->insert(TABLE_WORKFLOWACTION)->data($data)->exec();
  144. if(dao::isError())
  145. {
  146. $this->dao->rollBack();
  147. return false;
  148. }
  149. }
  150. }
  151. $this->dao->delete()->from(TABLE_WORKFLOWACTION)->where('module')->eq('feedback')->andWhere('action')->eq('view')->andWhere('vision')->eq('rnd')->exec();
  152. /* Insert fields of buildin modules to TABLE_WORKFLOWFIELD. */
  153. $data = new stdclass();
  154. $data->role = 'buildin';
  155. $data->createdBy = $account;
  156. $data->createdDate = $now;
  157. foreach($fields as $module => $moduleFields)
  158. {
  159. $order = 1;
  160. $data->module = $module;
  161. $currentVision = 'rnd';
  162. if(!empty($visions[$module])) $currentVision = $visions[$module];
  163. if($vision != 'all' && $vision != $currentVision) continue;
  164. foreach($moduleFields as $field => $options)
  165. {
  166. $data->field = $field;
  167. $data->name = isset($this->lang->$module->$field) ? $this->lang->$module->$field : $field;
  168. $data->type = zget($options, 'type', 'varchar');
  169. $data->length = zget($options, 'length', '');
  170. $data->control = zget($options, 'control', 'input');
  171. $data->options = zget($options, 'options', '[]');
  172. $data->default = zget($options, 'default', '');
  173. $data->buildin = zget($options, 'buildin', 1);
  174. $data->order = $order++;
  175. $data->readonly = ($field == 'subStatus') ? '0' : '1';
  176. $data->rules = zget($options, 'rules', '');
  177. if($module == 'execution')
  178. {
  179. $execField = 'exec' . ucfirst($field);
  180. if(isset($this->lang->$module->$execField)) $data->name = $this->lang->$module->$execField;
  181. }
  182. if(is_object($data->options) or is_array($data->options)) $data->options = helper::jsonEncode($data->options);
  183. $this->dao->delete()->from(TABLE_WORKFLOWFIELD)->where('module')->eq($module)->andWhere('field')->eq($field)->exec();
  184. $this->dao->insert(TABLE_WORKFLOWFIELD)->data($data)->exec();
  185. if(dao::isError())
  186. {
  187. $this->dao->rollBack();
  188. return false;
  189. }
  190. }
  191. }
  192. /* Insert labels of buildin modules to TABLE_WORKFLOWLABEL. */
  193. $data = new stdclass();
  194. $data->buildin = 1;
  195. $data->role = 'buildin';
  196. $data->params = '[]';
  197. $data->createdBy = $account;
  198. $data->createdDate = $now;
  199. foreach($modules as $app => $appModules)
  200. {
  201. foreach($appModules as $module => $options)
  202. {
  203. $labels = array();
  204. if($module == 'product')
  205. {
  206. if(isset($this->lang->product->featureBar['all'])) $labels = $this->lang->product->featureBar['all'];
  207. }
  208. elseif($module == 'story')
  209. {
  210. if(isset($this->lang->product->featureBar['browse'])) $labels = $this->lang->product->featureBar['browse'];
  211. }
  212. elseif($module == 'execution')
  213. {
  214. if(isset($this->lang->execution->featureBar['all'])) $labels = $this->lang->execution->featureBar['all'];
  215. }
  216. elseif($module == 'task')
  217. {
  218. if(isset($this->lang->execution->featureBar['task'])) $labels = $this->lang->execution->featureBar['task'];
  219. }
  220. elseif($module == 'bug')
  221. {
  222. if(isset($this->lang->bug->featureBar['browse'])) $labels = $this->lang->bug->featureBar['browse'];
  223. }
  224. elseif($module == 'feedback')
  225. {
  226. if(isset($this->lang->feedback->menu) && (is_object($this->lang->feedback->menu) || is_array($this->lang->feedback->menu)))
  227. {
  228. foreach($this->lang->feedback->menu as $key => $menuItem)
  229. {
  230. $menus = explode('|', zget($menuItem, 'link', $menuItem));
  231. $labels[$key] = zget($menus, 0, $menuItem);
  232. }
  233. }
  234. }
  235. else
  236. {
  237. if(isset($this->lang->$module->featureBar['browse'])) $labels = $this->lang->$module->featureBar['browse'];
  238. }
  239. $order = 1;
  240. $data->module = $module;
  241. $currentVision = 'rnd';
  242. if(!empty($visions[$module])) $currentVision = $visions[$module];
  243. if($vision != 'all' && $vision != $currentVision) continue;
  244. foreach($labels as $key => $label)
  245. {
  246. $data->code = $key;
  247. $data->label = trim(strip_tags($label));
  248. $data->order = $order++;
  249. $this->dao->delete()->from(TABLE_WORKFLOWLABEL)->where('module')->eq($module)->andWhere('code')->eq($key)->exec();
  250. $this->dao->insert(TABLE_WORKFLOWLABEL)->data($data)->exec();
  251. if(dao::isError())
  252. {
  253. $this->dao->rollBack();
  254. return false;
  255. }
  256. }
  257. }
  258. }
  259. if($vision == 'all')
  260. {
  261. $this->importLiteModules();
  262. if(dao::isError())
  263. {
  264. $this->dao->rollBack();
  265. return false;
  266. }
  267. }
  268. return $this->dao->commit();
  269. }
  270. /**
  271. * Import lite modules.
  272. *
  273. * @access public
  274. * @return bool
  275. */
  276. public function importLiteModules()
  277. {
  278. $this->loadModel('workflow');
  279. $this->loadModel('workflowaction');
  280. $this->loadModel('workflowlayout');
  281. $this->dao->begin();
  282. $liteModules = $this->config->workflow->buildin->liteModules;
  283. foreach($liteModules as $moduleName)
  284. {
  285. $workflow = $this->dao->select('*')->from(TABLE_WORKFLOW)->where('module')->eq($moduleName)->fetch();
  286. if(empty($workflow)) continue;
  287. unset($workflow->id, $workflow->editedBy, $workflow->editedDate);
  288. $workflow->vision = 'lite';
  289. if($workflow->module == 'task') $workflow->app = 'project';
  290. $this->dao->delete()->from(TABLE_WORKFLOW)->where('app')->eq($workflow->app)->andWhere('module')->eq($workflow->module)->andWhere('vision')->eq('lite')->exec();
  291. $this->dao->insert(TABLE_WORKFLOW)->data($workflow)->exec();
  292. if(dao::isError())
  293. {
  294. $this->dao->rollBack();
  295. return false;
  296. }
  297. $workflowActions = $this->dao->select('*')->from(TABLE_WORKFLOWACTION)->where('module')->eq($moduleName)->fetchAll('id', false);
  298. foreach($workflowActions as $workflowAction)
  299. {
  300. unset($workflowAction->id);
  301. $workflowAction->vision = 'lite';
  302. $this->dao->delete()->from(TABLE_WORKFLOWACTION)->where('module')->eq($workflowAction->module)->andWhere('action')->eq($workflowAction->action)->andWhere('vision')->eq('lite')->exec();
  303. if(empty($workflowAction->editeDate)) unset($workflowAction->editedDate);
  304. $this->dao->insert(TABLE_WORKFLOWACTION)->data($workflowAction)->exec();
  305. if(dao::isError())
  306. {
  307. $this->dao->rollBack();
  308. return false;
  309. }
  310. }
  311. $this->dao->delete()->from(TABLE_WORKFLOWACTION)->where('module')->eq('feedback')->andWhere('action')->eq('adminView')->andWhere('vision')->eq('lite')->exec();
  312. $workflowLayouts = $this->dao->select('*')->from(TABLE_WORKFLOWLAYOUT)
  313. ->where('module')->eq($moduleName)
  314. ->fetchAll('id', false);
  315. foreach($workflowLayouts as $workflowLayout)
  316. {
  317. unset($workflowLayout->id);
  318. $workflowLayout->vision = 'lite';
  319. $this->dao->delete()->from(TABLE_WORKFLOWLAYOUT)->where('module')->eq($workflowLayout->module)->andWhere('action')->eq($workflowLayout->action)->andWhere('field')->eq($workflowLayout->field)->andWhere('vision')->eq('lite')->exec();
  320. $this->dao->insert(TABLE_WORKFLOWLAYOUT)->data($workflowLayout)->exec();
  321. if(dao::isError())
  322. {
  323. $this->dao->rollBack();
  324. return false;
  325. }
  326. }
  327. }
  328. if(dao::isError())
  329. {
  330. $this->dao->rollBack();
  331. return false;
  332. }
  333. return $this->dao->commit();
  334. }
  335. /**
  336. * Add sub status for built-in modules.
  337. *
  338. * @access public
  339. * @return bool
  340. */
  341. public function addSubStatus()
  342. {
  343. $this->saveLogs('Run Method ' . __FUNCTION__);
  344. $this->app->loadModuleConfig('workflow');
  345. $modules = $this->config->workflow->buildin->subStatus->modules;
  346. $statusOrders = $this->dao->select('module, `order`')->from(TABLE_WORKFLOWFIELD)
  347. ->where('field')->eq('status')
  348. ->andWhere('module')->in($modules)
  349. ->fetchPairs();
  350. $field = new stdclass();
  351. $field->field = 'subStatus';
  352. $field->type = 'varchar';
  353. $field->length = 30;
  354. $field->control = 'select';
  355. $field->buildin = 0;
  356. $field->role = 'buildin';
  357. $field->options = '[]';
  358. $this->dao->begin();
  359. foreach($modules as $module)
  360. {
  361. $this->app->loadLang($module);
  362. $order = $statusOrders[$module] + 1;
  363. $field->module = $module;
  364. $field->name = $this->lang->$module->subStatus;
  365. $field->order = $order;
  366. $field->createdBy = isset($this->app->user->account) ? $this->app->user->account : 'admin';
  367. $field->createdDate = helper::now();
  368. $this->dao->delete()->from(TABLE_WORKFLOWFIELD)->where('module')->eq($module)->andWhere('field')->eq('subStatus')->exec();
  369. $this->dao->insert(TABLE_WORKFLOWFIELD)->data($field)->exec();
  370. $this->dao->update(TABLE_WORKFLOWFIELD)->set('`order` = `order` + 1')
  371. ->where('module')->eq($module)
  372. ->andWhere('`order`')->gt($order)
  373. ->exec();
  374. if(dao::isError())
  375. {
  376. $this->dao->rollBack();
  377. return false;
  378. }
  379. }
  380. return $this->dao->commit();
  381. }
  382. /**
  383. * Add batch create action and batch edit action for exist flows.
  384. *
  385. * @access public
  386. * @return bool
  387. */
  388. public function addDefaultActions()
  389. {
  390. $this->saveLogs('Run Method ' . __FUNCTION__);
  391. $this->loadModel('workflowaction');
  392. $actionLang = $this->lang->workflowaction->default;
  393. $actionConfig = $this->config->workflowaction->default;
  394. $defaultActions = $this->config->workflowaction->defaultActions;
  395. $flows = $this->dao->select('module,buildin')->from(TABLE_WORKFLOW)->where('type')->eq('flow')->fetchPairs('module', 'buildin');
  396. $action = new stdclass();
  397. $action->show = 'direct';
  398. $action->createdBy = isset($this->app->user->account) ? $this->app->user->account : 'admin';
  399. $action->createdDate = helper::now();
  400. foreach($flows as $module => $buildin)
  401. {
  402. if($buildin) continue;
  403. $action->module = $module;
  404. foreach($defaultActions as $actionCode)
  405. {
  406. $action->action = $actionCode;
  407. $action->name = $actionLang->actions[$actionCode];
  408. $action->type = $actionConfig->types[$actionCode];
  409. $action->batchMode = $actionConfig->batchModes[$actionCode];
  410. $action->open = $actionConfig->opens[$actionCode];
  411. $action->position = $actionConfig->positions[$actionCode];
  412. $this->dao->delete()->from(TABLE_WORKFLOWACTION)->where('module')->eq($module)->andWhere('action')->eq($actionCode)->andWhere('vision')->eq('rnd')->exec();
  413. $this->dao->insert(TABLE_WORKFLOWACTION)->data($action)->autoCheck()->exec();
  414. }
  415. }
  416. return !dao::isError();
  417. }
  418. /**
  419. * process sub tables.
  420. *
  421. * @access public
  422. * @return void
  423. */
  424. public function processSubTables()
  425. {
  426. $this->saveLogs('Run Method ' . __FUNCTION__);
  427. $subTables = $this->dao->select('parent, module')->from(TABLE_WORKFLOW)
  428. ->where('parent')->ne('')
  429. ->andWhere('type')->eq('table')
  430. ->fetchPairs();
  431. foreach($subTables as $parent => $module)
  432. {
  433. $this->dao->update(TABLE_WORKFLOWLAYOUT)
  434. ->set('field')->eq('sub_' . $module)
  435. ->where('module')->eq($parent)
  436. ->andWhere('field')->eq($module)
  437. ->exec();
  438. }
  439. return !dao::isError();
  440. }
  441. /**
  442. * Import caselib module for workflow.
  443. *
  444. * @access public
  445. * @return void
  446. */
  447. public function importCaseLibModule()
  448. {
  449. $this->saveLogs('Run Method ' . __FUNCTION__);
  450. $this->loadModel('workflow');
  451. $this->loadModel('workflowaction');
  452. $this->loadModel('workflowfield');
  453. $this->dao->delete()->from(TABLE_WORKFLOW)->where('module')->eq('caselib')->exec();
  454. $this->dao->delete()->from(TABLE_WORKFLOWACTION)->where('module')->eq('caselib')->exec();
  455. $this->dao->delete()->from(TABLE_WORKFLOWFIELD)->where('module')->eq('caselib')->exec();
  456. $caselibOptions = $this->config->workflow->buildin->modules->qa->caselib;
  457. $actions = $this->config->workflowaction->buildin->actions['caselib'];
  458. $actionOpens = $this->config->workflowaction->buildin->opens['caselib'];
  459. $fields = $this->config->workflowfield->buildin->fields['caselib'];
  460. $account = isset($this->app->user->account) ? $this->app->user->account : 'admin';
  461. $now = helper::now();
  462. /* Insert buildin modules to TABLE_WORKFLOW. */
  463. $this->app->loadLang('caselib');
  464. $data = new stdclass();
  465. $data->buildin = 1;
  466. $data->vision = 'rnd';
  467. $data->createdBy = $account;
  468. $data->createdDate = $now;
  469. $data->app = 'qa';
  470. $data->module = 'caselib';
  471. $data->status = 'normal';
  472. $data->name = isset($this->lang->caselib->common) ? $this->lang->caselib->common : 'caselib';
  473. $data->table = str_replace('`', '', zget($caselibOptions, 'table', ''));
  474. $data->navigator = zget($caselibOptions, 'navigator', 'secondary');
  475. $this->dao->insert(TABLE_WORKFLOW)->data($data)->exec();
  476. /* Insert actions of buildin modules to TABLE_WORKFLOWACTION. */
  477. $data = new stdclass();
  478. $data->buildin = 1;
  479. $data->extensionType = 'none';
  480. $data->createdBy = $account;
  481. $data->createdDate = $now;
  482. $data->module = 'caselib';
  483. $data->role = 'buildin';
  484. foreach($actions as $action)
  485. {
  486. $data->action = $action;
  487. $data->name = isset($this->lang->caselib->$action) ? $this->lang->caselib->$action : $action;
  488. $data->open = isset($actionOpens['caselib'][$action]) ? $actionOpens['caselib'][$action] : 'normal';
  489. $data->method = isset($this->config->workflowaction->buildin->methods['caselib'][$action]) ? $this->config->workflowaction->buildin->methods['caselib'][$action] : $action;
  490. $data->layout = 'normal';
  491. $this->dao->insert(TABLE_WORKFLOWACTION)->data($data)->exec();
  492. }
  493. /* Insert fields of buildin modules to TABLE_WORKFLOWFIELD. */
  494. $data = new stdclass();
  495. $data->createdBy = $account;
  496. $data->createdDate = $now;
  497. $data->module = 'caselib';
  498. $order = 1;
  499. foreach($fields as $field => $options)
  500. {
  501. $data->field = $field;
  502. $data->name = isset($this->lang->caselib->$field) ? $this->lang->caselib->$field : $field;
  503. $data->type = zget($options, 'type', 'varchar');
  504. $data->length = zget($options, 'length', '');
  505. $data->control = zget($options, 'control', 'input');
  506. $data->options = zget($options, 'options', '[]');
  507. $data->default = zget($options, 'default', '');
  508. $data->buildin = zget($options, 'buildin', 1);
  509. $data->order = $order++;
  510. $data->role = 'buildin';
  511. $data->readonly = ($field == 'subStatus') ? '0' : '1';
  512. if(is_object($data->options) or is_array($data->options)) $data->options = helper::jsonEncode($data->options);
  513. $this->dao->insert(TABLE_WORKFLOWFIELD)->data($data)->exec();
  514. }
  515. }
  516. /**
  517. * Import epic and requirement modules for workflow.
  518. *
  519. * @access public
  520. * @return void
  521. */
  522. public function importERURModules()
  523. {
  524. $this->saveLogs('Run Method ' . __FUNCTION__);
  525. $this->loadModel('workflow');
  526. $this->loadModel('workflowaction');
  527. $this->loadModel('workflowfield');
  528. $this->loadModel('workflowlayout');
  529. $this->dao->delete()->from(TABLE_WORKFLOW)->where('module')->in('requirement, epic')->exec();
  530. $this->dao->delete()->from(TABLE_WORKFLOWACTION)->where('module')->in('requirement, epic')->exec();
  531. $this->dao->delete()->from(TABLE_WORKFLOWFIELD)->where('module')->in('requirement, epic')->exec();
  532. $this->dao->delete()->from(TABLE_WORKFLOWLAYOUT)->where('module')->in('requirement, epic')->exec();
  533. $account = isset($this->app->user->account) ? $this->app->user->account : 'admin';
  534. $now = helper::now();
  535. /* Insert buildin modules to TABLE_WORKFLOW. */
  536. $this->app->loadLang('story');
  537. foreach(array('requirement', 'epic') as $module)
  538. {
  539. $this->app->loadLang($module);
  540. $data = new stdclass();
  541. $data->buildin = 1;
  542. $data->vision = 'rnd';
  543. $data->createdBy = $account;
  544. $data->createdDate = $now;
  545. $data->app = 'product';
  546. $data->module = $module;
  547. $data->name = $module == 'epic' ? $this->lang->ERCommon : $this->lang->URCommon;
  548. $data->table = str_replace('`', '', TABLE_STORY);
  549. $data->navigator = 'secondary';
  550. $data->status = 'normal';
  551. $this->dao->insert(TABLE_WORKFLOW)->data($data)->exec();
  552. /*用户需求直接用软件需求的工作流,业务需求用配置里的。 */
  553. if($module == 'requirement')
  554. {
  555. $actions = $this->dao->select('*')->from(TABLE_WORKFLOWACTION)->where('module')->eq('story')->fetchAll('id', false);
  556. foreach($actions as $action)
  557. {
  558. unset($action->id);
  559. $action->module = 'requirement';
  560. $action->name = str_replace($this->lang->story->common, $this->lang->URCommon, $action->name);
  561. $this->dao->insert(TABLE_WORKFLOWACTION)->data($action)->exec();
  562. }
  563. $fields = $this->dao->select('*')->from(TABLE_WORKFLOWFIELD)->where('module')->eq('story')->fetchAll('id', false);
  564. foreach($fields as $field)
  565. {
  566. unset($field->id);
  567. $field->module = 'requirement';
  568. $field->name = str_replace($this->lang->story->common, $this->lang->URCommon, $field->name);
  569. $this->dao->insert(TABLE_WORKFLOWFIELD)->data($field)->exec();
  570. }
  571. $layouts = $this->dao->select('*')->from(TABLE_WORKFLOWLAYOUT)->where('module')->eq('story')->fetchAll('id', false);
  572. foreach($layouts as $layout)
  573. {
  574. unset($layout->id);
  575. $layout->module = 'requirement';
  576. $this->dao->insert(TABLE_WORKFLOWLAYOUT)->data($layout)->exec();
  577. }
  578. }
  579. else
  580. {
  581. $actions = $this->config->workflowaction->buildin->actions['epic'];
  582. $actionOpens = $this->config->workflowaction->buildin->opens['epic'];
  583. $fields = $this->config->workflowfield->buildin->fields['epic'];
  584. $layouts = $this->config->workflowlayout->buildin->layouts->epic;
  585. /* Insert actions of buildin modules to TABLE_WORKFLOWACTION. */
  586. $data = new stdclass();
  587. $data->buildin = 1;
  588. $data->role = 'buildin';
  589. $data->extensionType = 'none';
  590. $data->createdBy = $account;
  591. $data->createdDate = $now;
  592. $data->module = 'epic';
  593. foreach($actions as $action)
  594. {
  595. $data->action = $action;
  596. $data->name = isset($this->lang->epic->$action) ? $this->lang->epic->$action : $action;
  597. $data->open = isset($actionOpens['epic'][$action]) ? $actionOpens['epic'][$action] : 'normal';
  598. $data->layout = 'normal';
  599. $this->dao->insert(TABLE_WORKFLOWACTION)->data($data)->exec();
  600. }
  601. /* Insert fields of buildin modules to TABLE_WORKFLOWFIELD. */
  602. $data = new stdclass();
  603. $data->createdBy = $account;
  604. $data->createdDate = $now;
  605. $data->module = 'epic';
  606. $order = 1;
  607. foreach($fields as $field => $options)
  608. {
  609. $data->field = $field;
  610. $data->role = 'buildin';
  611. $data->name = isset($this->lang->epic->field) ? $this->lang->epic->$field : $field;
  612. $data->type = zget($options, 'type', 'varchar');
  613. $data->length = zget($options, 'length', '');
  614. $data->control = zget($options, 'control', 'input');
  615. $data->options = zget($options, 'options', '[]');
  616. $data->default = zget($options, 'default', '');
  617. $data->buildin = zget($options, 'buildin', 1);
  618. $data->order = $order++;
  619. $data->readonly = ($field == 'subStatus') ? '0' : '1';
  620. if(is_object($data->options) or is_array($data->options)) $data->options = helper::jsonEncode($data->options);
  621. $this->dao->insert(TABLE_WORKFLOWFIELD)->data($data)->exec();
  622. }
  623. /* Insert layouts of buildin modules to TABLE_WORKFLOWLAYOUT. */
  624. $data = new stdclass();
  625. $data->module = 'epic';
  626. foreach($layouts as $action => $layoutFields)
  627. {
  628. $order = 1;
  629. $data->action = $action;
  630. foreach($layoutFields as $field => $options)
  631. {
  632. $data->field = $field;
  633. $data->width = zget($options, 'width', 0);
  634. $data->mobileShow = zget($options, 'mobileShow', 0);
  635. $data->order = $order++;
  636. if($data->width == 'auto') $data->width = 0;
  637. $this->dao->insert(TABLE_WORKFLOWLAYOUT)->data($data)->exec();
  638. }
  639. }
  640. }
  641. }
  642. }
  643. /**
  644. * Delete buildin fields.
  645. *
  646. * @access public
  647. * @return void
  648. */
  649. public function deleteBuildinFields()
  650. {
  651. $this->saveLogs('Run Method ' . __FUNCTION__);
  652. $deleteIdList = $this->dao->select('t1.id')->from(TABLE_WORKFLOWLAYOUT)->alias('t1')
  653. ->leftJoin(TABLE_WORKFLOWFIELD)->alias('t2')->on('t1.field=t2.field && t1.module = t2.module')
  654. ->leftJoin(TABLE_WORKFLOWACTION)->alias('t3')->on('t1.action=t3.action && t1.module = t3.module')
  655. ->where('t2.buildin')->eq(1)
  656. ->andWhere('t3.extensionType')->eq('extend')
  657. ->fetchPairs('id', 'id');
  658. $this->dao->delete()->from(TABLE_WORKFLOWLAYOUT)->where('id')->in($deleteIdList)->exec();
  659. }
  660. /**
  661. * Add new actions for exist flows.
  662. *
  663. * @access public
  664. * @return bool
  665. */
  666. public function addWorkflowActions()
  667. {
  668. $this->saveLogs('Run Method ' . __FUNCTION__);
  669. $this->loadModel('workflowaction');
  670. $newActions = array('batchcreate', 'batchedit', 'link', 'unlink', 'exporttemplate', 'import', 'showimport');
  671. $actionLang = $this->lang->workflowaction->default;
  672. $actionConfig = $this->config->workflowaction->default;
  673. $flows = $this->dao->select('module,buildin')->from(TABLE_WORKFLOW)->where('type')->eq('flow')->fetchPairs('module', 'buildin');
  674. $action = new stdclass();
  675. $action->show = 'direct';
  676. $action->layout = 'normal';
  677. $action->createdBy = isset($this->app->user->account) ? $this->app->user->account : 'admin';
  678. $action->createdDate = helper::now();
  679. foreach($flows as $module => $buildin)
  680. {
  681. $action->module = $module;
  682. $action->buildin = $buildin;
  683. $action->extensionType = $buildin ? 'none' : 'override';
  684. foreach($newActions as $actionCode)
  685. {
  686. if($buildin and !in_array($actionCode, zget($this->config->workflowaction->buildin->actions, $module, array()))) continue;
  687. $open = $actionConfig->opens[$actionCode];
  688. if($buildin and isset($this->config->workflowaction->buildin->opens[$module][$actionCode])) $open = $this->config->workflowaction->buildin->opens[$module][$actionCode];
  689. $action->open = $open;
  690. $action->action = $actionCode;
  691. $action->name = $actionLang->actions[$actionCode];
  692. $action->type = $actionConfig->types[$actionCode];
  693. $action->batchMode = $actionConfig->batchModes[$actionCode];
  694. $action->position = $actionConfig->positions[$actionCode];
  695. $this->dao->delete()->from(TABLE_WORKFLOWACTION)->where('module')->eq($module)->andWhere('action')->eq($actionCode)->andWhere('vision')->eq('rnd')->exec();
  696. $this->dao->insert(TABLE_WORKFLOWACTION)->data($action)->autoCheck()->exec();
  697. }
  698. }
  699. $this->dao->update(TABLE_WORKFLOWACTION)->set('name')->eq($actionLang->actions['export'])->where('action')->eq('export')->exec();
  700. return !dao::isError();
  701. }
  702. /**
  703. * Process workflow layout.
  704. *
  705. * @access public
  706. * @return bool
  707. */
  708. public function processWorkflowLayout()
  709. {
  710. $this->saveLogs('Run Method ' . __FUNCTION__);
  711. $subTables = $this->dao->select('parent, module')->from(TABLE_WORKFLOW)
  712. ->where('parent')->ne('')
  713. ->andWhere('type')->eq('table')
  714. ->fetchPairs();
  715. foreach($subTables as $parent => $module)
  716. {
  717. $this->dao->update(TABLE_WORKFLOWLAYOUT)
  718. ->set('field')->eq('sub_' . $module)
  719. ->where('module')->eq($parent)
  720. ->andWhere('field')->eq($module)
  721. ->exec();
  722. }
  723. return !dao::isError();
  724. }
  725. /**
  726. * Make sure the params of a label has the condition deleted='0'.
  727. *
  728. * @access public
  729. * @return bool
  730. */
  731. public function processWorkflowLabel()
  732. {
  733. $this->saveLogs('Run Method ' . __FUNCTION__);
  734. $labels = $this->dao->select('id, params')->from(TABLE_WORKFLOWLABEL)->where('module')->eq('test')->fetchPairs();
  735. foreach($labels as $id => $params)
  736. {
  737. $index = 0;
  738. $deleted = false;
  739. $params = json_decode($params, true);
  740. foreach($params as $index => $param)
  741. {
  742. if(zget($param, 'field') == 'deleted' && zget($param, 'operator') == '=' && zget($param, 'value') == '0')
  743. {
  744. $deleted = true;
  745. break;
  746. }
  747. }
  748. if(!$deleted)
  749. {
  750. $index++;
  751. $params[$index]['field'] = 'deleted';
  752. $params[$index]['operator'] = '=';
  753. $params[$index]['value'] = '0';
  754. $params = array_reverse($params);
  755. }
  756. $params = helper::jsonEncode($params);
  757. $this->dao->update(TABLE_WORKFLOWLABEL)->set('params')->eq($params)->where('id')->eq($id)->exec();
  758. }
  759. return !dao::isError();
  760. }
  761. /**
  762. * Process workflow conditions to array.
  763. *
  764. * @access public
  765. * @return bool
  766. */
  767. public function processWorkflowCondition()
  768. {
  769. $this->saveLogs('Run Method ' . __FUNCTION__);
  770. $actions = $this->dao->select('id, conditions')->from(TABLE_WORKFLOWACTION)->fetchPairs();
  771. foreach($actions as $id => $conditions)
  772. {
  773. $conditions = json_decode($conditions);
  774. if(!$conditions) continue;
  775. $conditions = helper::jsonEncode(array($conditions));
  776. $this->dao->update(TABLE_WORKFLOWACTION)->set('conditions')->eq($conditions)->where('id')->eq($id)->exec();
  777. }
  778. return !dao::isError();
  779. }
  780. /**
  781. * Process workflow fields.
  782. *
  783. * @access public
  784. * @return void
  785. */
  786. public function processWorkflowFields()
  787. {
  788. $sqls['id'] = "ALTER TABLE %s CHANGE `id` `id` mediumint(8) unsigned NOT NULL AUTO_INCREMENT";
  789. $sqls['parent'] = "ALTER TABLE %s CHANGE `parent` `parent` mediumint(8) unsigned NOT NULL";
  790. $sqls['assignedTo'] = "ALTER TABLE %s CHANGE `assignedTo` `assignedTo` varchar(30) NOT NULL";
  791. $sqls['status'] = "ALTER TABLE %s CHANGE `status` `status` varchar(30) NOT NULL";
  792. $sqls['subStatus'] = "ALTER TABLE %s CHANGE `subStatus` `subStatus` varchar(30) NOT NULL";
  793. $sqls['createdBy'] = "ALTER TABLE %s CHANGE `createdBy` `createdBy` varchar(30) NOT NULL";
  794. $sqls['createdDate'] = "ALTER TABLE %s CHANGE `createdDate` `createdDate` datetime NOT NULL";
  795. $sqls['editedBy'] = "ALTER TABLE %s CHANGE `editedBy` `editedBy` varchar(30) NOT NULL";
  796. $sqls['editedDate'] = "ALTER TABLE %s CHANGE `editedDate` `editedDate` datetime NOT NULL";
  797. $sqls['assignedBy'] = "ALTER TABLE %s CHANGE `assignedBy` `assignedBy` varchar(30) NOT NULL";
  798. $sqls['assignedDate'] = "ALTER TABLE %s CHANGE `assignedDate` `assignedDate` datetime NOT NULL";
  799. $sqls['deleted'] = "ALTER TABLE %s CHANGE `deleted` `deleted` enum('0', '1') NOT NULL DEFAULT '0'";
  800. $flows = $this->dao->select('module, `table`')->from(TABLE_WORKFLOW)
  801. ->where('type')->eq('flow')
  802. ->andWhere('buildin')->eq('0')
  803. ->orderBy('id_desc')
  804. ->fetchPairs();
  805. $fields = $this->dao->select('module, field, `default`')->from(TABLE_WORKFLOWFIELD)
  806. ->where('module')->in(array_keys($flows))
  807. ->fetchGroup('module', 'field');
  808. $magicQuote = (version_compare(phpversion(), '5.4', '<') and function_exists('get_magic_quotes_gpc') and get_magic_quotes_gpc());
  809. foreach($flows as $module => $table)
  810. {
  811. foreach($sqls as $field => $sql)
  812. {
  813. if(!isset($fields[$module][$field])) continue;
  814. $sql = sprintf($sql, $table);
  815. if($field == 'status' or $field == 'subStatus')
  816. {
  817. $default = $fields[$module][$field]->default;
  818. if($default)
  819. {
  820. if($magicQuote) $default = stripslashes($default);
  821. $default = $this->dbh->quote($default);
  822. $sql .= " DEFAULT {$default}";
  823. }
  824. }
  825. try
  826. {
  827. $this->dbh->query($sql);
  828. }
  829. catch(PDOException $e)
  830. {
  831. self::$errors[] = $e->getMessage() . "<p>The sql is: $sql</p>";
  832. return false;
  833. }
  834. }
  835. }
  836. return true;
  837. }
  838. public function processFlowStatus()
  839. {
  840. $this->loadModel('workflow', 'flow');
  841. $this->app->loadLang('workflowfield', 'flow');
  842. $this->app->loadModuleConfig('workflowfield', 'flow');
  843. $flowPairs = $this->dao->select('module')->from(TABLE_WORKFLOW)->where('type')->eq('flow')->andWhere('buildin')->eq(0)->fetchPairs();
  844. foreach($flowPairs as $module)
  845. {
  846. $errors = array();
  847. $actions = $this->dao->select('action, name')->from(TABLE_WORKFLOWACTION)->where('module')->eq($module)->andWhere('open')->ne('none')->fetchPairs();
  848. $fields = $this->dao->select('id')->from(TABLE_WORKFLOWFIELD)->where('module')->eq($module)->andWhere('field')->notin(array_keys($this->config->workflowfield->default->fields))->fetchPairs();
  849. $layoutFields = $this->dao->select('DISTINCT action')->from(TABLE_WORKFLOWLAYOUT)->where('module')->eq($module)->andWhere('action')->in(array_keys($actions))->andWhere('field')->notin('actions,file')->fetchPairs();
  850. foreach($actions as $action => $name)
  851. {
  852. if(isset($layoutFields[$action]))
  853. {
  854. unset($actions[$action]);
  855. continue;
  856. }
  857. }
  858. if(empty($fields)) $errors[] = 'emptyCustomField';
  859. if(!empty($actions)) $errors[] = 'emptyLayout';
  860. $status = !empty($errors) ? 'wait' : 'normal';
  861. $this->dao->update(TABLE_WORKFLOW)->set('status')->eq($status)->where('module')->eq($module)->exec();
  862. }
  863. return !dao::isError();
  864. }
  865. public function addMailtoFields()
  866. {
  867. $this->app->loadLang('workflowfield');
  868. $mailto = new stdclass();
  869. $mailto->field = 'mailto';
  870. $mailto->control = 'multi-select';
  871. $mailto->type = 'text';
  872. $mailto->name = $this->lang->workflowfield->default->fields['mailto'];
  873. $mailto->options = 'user';
  874. $mailto->readonly = 1;
  875. $flows = $this->dao->select('module, `table`')->from(TABLE_WORKFLOW)->where('`type`')->eq('flow')->fetchPairs();
  876. foreach($flows as $module => $table)
  877. {
  878. $hasMailto = false;
  879. $fields = $this->dbh->query("DESC $table")->fetchAll();
  880. foreach($fields as $field)
  881. {
  882. if($field->Field == 'mailto')
  883. {
  884. $hasMailto = true;
  885. break;
  886. }
  887. }
  888. if(!$hasMailto)
  889. {
  890. $mailto->module = $module;
  891. $this->dao->insert(TABLE_WORKFLOWFIELD)->data($mailto)->autoCheck()->exec();
  892. if(dao::isError()) return false;
  893. try
  894. {
  895. $sql = "ALTER TABLE `{$table}` ADD `mailto` text NOT NULL";
  896. $this->dbh->query($sql);
  897. }
  898. catch(PDOException $exception)
  899. {
  900. self::$errors[] = $exception->getMessage() . "<p>The sql is: $sql</p>";
  901. return false;
  902. }
  903. }
  904. }
  905. return true;
  906. }
  907. /**
  908. * Update attend status.
  909. *
  910. * @access public
  911. * @return bool
  912. */
  913. public function updateAttendStatus()
  914. {
  915. /* Get leave list. */
  916. $leaveList = $this->loadModel('leave')->getList('personal', '', '', '', '', 'pass');
  917. /* Cycle leave list to modify the attend status. */
  918. foreach($leaveList as $leave)
  919. {
  920. $this->dao->update(TABLE_ATTEND)
  921. ->set('status')->eq('leave')
  922. ->set('reason')->eq('leave')
  923. ->where('`date`')->between($leave->begin, $leave->end)
  924. ->andWhere('account')->eq($leave->createdBy)
  925. ->exec();
  926. }
  927. return true;
  928. }
  929. /**
  930. * Init view for workflow datasource.
  931. *
  932. * @access public
  933. * @return bool
  934. */
  935. public function initView4WorkflowDatasource()
  936. {
  937. $datasources = $this->dao->select('*')->from(TABLE_WORKFLOWDATASOURCE)->where('type')->eq('sql')->andWhere('view')->eq('')->fetchAll('id', false);
  938. foreach($datasources as $id => $datasource)
  939. {
  940. $options = array();
  941. try
  942. {
  943. $view = 'view_datasource_tmp';
  944. $sql = "CREATE VIEW $view AS {$datasource->datasource}";
  945. $this->dbh->query($sql);
  946. $fields = $this->dbh->query("DESC $view")->fetchAll();
  947. foreach($fields as $field) $options[$field->Field] = $field->Field;
  948. $sql = "DROP VIEW $view";
  949. $this->dbh->query($sql);
  950. }
  951. catch(PDOException $exception)
  952. {
  953. }
  954. try
  955. {
  956. $view = "view_datasource_$id";
  957. $keyField = array_shift($options);
  958. $valueField = array_shift($options);
  959. $sqls = array();
  960. $sqls[] = "DROP VIEW IF EXISTS $view";
  961. $sqls[] = "CREATE VIEW $view AS $datasource->datasource";
  962. foreach($sqls as $sql) $this->dbh->query($sql);
  963. $this->dao->update(TABLE_WORKFLOWDATASOURCE)->set('view')->eq($view)->set('keyField')->eq($keyField)->set('valueField')->eq($valueField)->where('id')->eq($id)->exec();
  964. }
  965. catch(PDOException $exception)
  966. {
  967. dao::getError();
  968. }
  969. }
  970. return true;
  971. }
  972. /**
  973. * Adjust priv for biz5_0_1.
  974. *
  975. * @access public
  976. * @return bool
  977. */
  978. public function adjustPrivBiz5_0_1()
  979. {
  980. $groups = $this->dao->select('id')->from(TABLE_GROUP)->where('developer')->eq('0')->fetchPairs();
  981. $this->dao->delete()->from(TABLE_GROUPPRIV)->where('module')->eq('my')->andWhere('method')->in('calendar,todo')->andWhere('`group`')->in($groups)->exec();
  982. $this->dao->delete()->from(TABLE_GROUPPRIV)->where('module')->eq('todo')->andWhere('method')->eq('calendar')->andWhere('`group`')->in($groups)->exec();
  983. $priv = new stdclass();
  984. foreach($groups as $group)
  985. {
  986. $priv->group = $group;
  987. $priv->module = 'my';
  988. $priv->method = 'calendar';
  989. $this->dao->insert(TABLE_GROUPPRIV)->data($priv)->exec();
  990. $priv->method = 'todo';
  991. $this->dao->insert(TABLE_GROUPPRIV)->data($priv)->exec();
  992. $priv->module = 'todo';
  993. $priv->method = 'calendar';
  994. $this->dao->insert(TABLE_GROUPPRIV)->data($priv)->exec();
  995. }
  996. return true;
  997. }
  998. public function updateWorkflow4Execution()
  999. {
  1000. $workflowAction = $this->dao->select('*')->from(TABLE_WORKFLOWACTION)->where('module')->eq('execution')->andWhere('action')->eq('create')->fetch();
  1001. if(empty($workflowAction))
  1002. {
  1003. $this->dao->update(TABLE_WORKFLOWACTION)->set('module')->eq('execution')->where('module')->eq('project')->exec();
  1004. $this->dao->delete()->from(TABLE_WORKFLOWACTION)->where('module')->eq('execution')->andWhere('action')->eq('browse')->exec();
  1005. $this->dao->exec("REPLACE INTO " . TABLE_WORKFLOWACTION . "(`module`, `action`, `name`, `type`, `batchMode`, `extensionType`, `open`, `position`, `layout`, `show`, `order`, `buildin`, `virtual`, `conditions`, `verifications`, `hooks`, `linkages`, `js`, `css`, `toList`, `blocks`, `desc`, `status`, `createdBy`, `createdDate`, `editedBy`, `editedDate`) VALUES
  1006. ('project', 'browse', '项目列表', 'single', 'different', 'none', 'normal', 'browseandview', 'normal', 'dropdownlist', 0, 1, 0, '', '', '', '', '', '', '', '', '', 'enable', '', '2021-07-28 16:54:38', '', '0000-00-00 00:00:00'),
  1007. ('project', 'create', '创建项目', 'single', 'different', 'none', 'normal', 'browseandview', 'normal', 'dropdownlist', 0, 1, 0, '', '', '', '', '', '', '', '', '', 'enable', '', '2021-07-28 16:54:38', '', '0000-00-00 00:00:00'),
  1008. ('project', 'batchedit', '批量编辑', 'single', 'different', 'none', 'normal', 'browseandview', 'normal', 'dropdownlist', 0, 1, 0, '', '', '', '', '', '', '', '', '', 'enable', '', '2021-07-28 16:54:38', '', '0000-00-00 00:00:00'),
  1009. ('project', 'edit', '编辑项目', 'single', 'different', 'none', 'normal', 'browseandview', 'normal', 'dropdownlist', 0, 1, 0, '', '', '', '', '', '', '', '', '', 'enable', '', '2021-07-28 16:54:38', '', '0000-00-00 00:00:00'),
  1010. ('project', 'view', '项目概况', 'single', 'different', 'none', 'normal', 'browseandview', 'side', 'dropdownlist', 0, 1, 0, '', '', '', '', '', '', '', '', '', 'enable', '', '2021-07-28 16:54:38', '', '0000-00-00 00:00:00'),
  1011. ('project', 'delete', '删除项目', 'single', 'different', 'none', 'none', 'browseandview', 'normal', 'dropdownlist', 0, 1, 0, '', '', '', '', '', '', '', '', '', 'enable', '', '2021-07-28 16:54:38', '', '0000-00-00 00:00:00'),
  1012. ('project', 'close', '关闭项目', 'single', 'different', 'none', 'modal', 'browseandview', 'normal', 'dropdownlist', 0, 1, 0, '', '', '', '', '', '', '', '', '', 'enable', '', '2021-07-28 16:54:38', '', '0000-00-00 00:00:00'),
  1013. ('project', 'activate', '激活项目', 'single', 'different', 'none', 'modal', 'browseandview', 'normal', 'dropdownlist', 0, 1, 0, '', '', '', '', '', '', '', '', '', 'enable', '', '2021-07-28 16:54:38', '', '0000-00-00 00:00:00'),
  1014. ('project', 'start', '启动项目', 'single', 'different', 'none', 'modal', 'browseandview', 'normal', 'dropdownlist', 0, 1, 0, '', '', '', '', '', '', '', '', '', 'enable', '', '2021-07-28 16:54:38', '', '0000-00-00 00:00:00'),
  1015. ('project', 'suspend', '挂起项目', 'single', 'different', 'none', 'modal', 'browseandview', 'normal', 'dropdownlist', 0, 1, 0, '', '', '', '', '', '', '', '', '', 'enable', '', '2021-07-28 16:54:38', '', '0000-00-00 00:00:00'),
  1016. ('execution', 'task', '任务列表', 'single', 'different', 'none', 'normal', 'browseandview', 'normal', 'dropdownlist', 0, 1, 0, '', '', '', '', '', '', '', '', '', 'enable', '', '2021-07-28 16:54:38', '', '0000-00-00 00:00:00')");
  1017. }
  1018. $workflowField = $this->dao->select('*')->from(TABLE_WORKFLOWFIELD)->where('module')->eq('execution')->limit(1)->fetch();
  1019. if(empty($workflowField))
  1020. {
  1021. $this->dao->update(TABLE_WORKFLOWFIELD)->set('module')->eq('execution')->where('module')->eq('project')->exec();
  1022. $this->dao->update(TABLE_WORKFLOWFIELD)->set('field')->eq('project')->where('module')->eq('execution')->andWhere('field')->eq('parent')->exec();
  1023. $this->dao->exec("REPLACE INTO " . TABLE_WORKFLOWFIELD . " (`module`, `field`, `type`, `length`, `name`, `control`, `expression`, `options`, `default`, `rules`, `placeholder`, `order`, `searchOrder`, `exportOrder`, `canExport`, `canSearch`, `isValue`, `readonly`, `buildin`, `desc`, `createdBy`, `createdDate`, `editedBy`, `editedDate`) VALUES
  1024. ('project', 'id', 'mediumint', '8', '编号', 'input', '', '', '', '', '', 1, 0, 0, '0', '0', '0', '1', 1, '', '', '2021-07-28 16:54:38', 'admin', '2021-07-28 16:58:48'),
  1025. ('project', 'type', 'varchar', '20', '项目类型', 'select', '', '16', 'sprint', '', '', 2, 0, 0, '0', '0', '0', '1', 1, '', '', '2021-07-28 16:54:38', '', '0000-00-00 00:00:00'),
  1026. ('project', 'model', 'char', '30', '项目管理方式', 'input', '', '', '', '', '', 3, 0, 0, '0', '0', '0', '1', 1, '', '', '2021-07-28 16:54:38', 'admin', '2021-07-28 16:58:30'),
  1027. ('project', 'parent', 'mediumint', '8', '所属项目集', 'input', '', '', '0', '', '', 4, 0, 0, '0', '0', '0', '1', 1, '', '', '2021-07-28 16:54:38', '', '0000-00-00 00:00:00'),
  1028. ('project', 'name', 'varchar', '90', '项目名称', 'input', '', '', '', '', '', 5, 0, 0, '0', '0', '0', '1', 1, '', '', '2021-07-28 16:54:38', '', '0000-00-00 00:00:00'),
  1029. ('project', 'budget', 'varchar', '30', '预算', 'input', '', '', '0', '', '', 7, 0, 0, '0', '0', '0', '1', 1, '', '', '2021-07-28 16:54:38', '', '0000-00-00 00:00:00'),
  1030. ('project', 'budgetUnit', 'char', '30', '预算单位', 'input', '', '', 'CNY', '', '', 8, 0, 0, '0', '0', '0', '1', 1, '', '', '2021-07-28 16:54:38', 'admin', '2021-07-28 16:58:42'),
  1031. ('project', 'begin', 'date', '', '计划开始', 'input', '', '', '', '', '', 9, 0, 0, '0', '0', '0', '1', 1, '', '', '2021-07-28 16:54:38', '', '0000-00-00 00:00:00'),
  1032. ('project', 'end', 'date', '', '计划完成', 'input', '', '', '', '', '', 10, 0, 0, '0', '0', '0', '1', 1, '', '', '2021-07-28 16:54:38', '', '0000-00-00 00:00:00'),
  1033. ('project', 'days', 'smallint', '5', '可用工作日', 'input', '', '', '', '', '', 11, 0, 0, '0', '0', '0', '1', 1, '', '', '2021-07-28 16:54:38', '', '0000-00-00 00:00:00'),
  1034. ('project', 'status', 'varchar', '10', '状态', 'select', '', '17', '', '', '', 12, 0, 0, '0', '0', '0', '1', 1, '', '', '2021-07-28 16:54:38', '', '0000-00-00 00:00:00'),
  1035. ('project', 'stage', 'enum', '', '阶段', 'input', '', '', '1', '', '', 13, 0, 0, '0', '0', '0', '1', 1, '', '', '2021-07-28 16:54:38', '', '0000-00-00 00:00:00'),
  1036. ('project', 'pri', 'enum', '', '优先级', 'input', '', '', '1', '', '', 15, 0, 0, '0', '0', '0', '1', 1, '', '', '2021-07-28 16:54:38', '', '0000-00-00 00:00:00'),
  1037. ('project', 'desc', 'text', '', '项目描述', 'input', '', '', '', '', '', 16, 0, 0, '0', '0', '0', '1', 1, '', '', '2021-07-28 16:54:38', '', '0000-00-00 00:00:00'),
  1038. ('project', 'openedBy', 'varchar', '30', '由谁创建', 'select', '', 'user', '', '', '', 17, 0, 0, '0', '0', '0', '1', 1, '', '', '2021-07-28 16:54:38', '', '0000-00-00 00:00:00'),
  1039. ('project', 'openedDate', 'datetime', '', '创建日期', 'input', '', '', '', '', '', 18, 0, 0, '0', '0', '0', '1', 1, '', '', '2021-07-28 16:54:38', '', '0000-00-00 00:00:00'),
  1040. ('project', 'closedBy', 'varchar', '30', '由谁关闭', 'select', '', 'user', '', '', '', 19, 0, 0, '0', '0', '0', '1', 1, '', '', '2021-07-28 16:54:38', '', '0000-00-00 00:00:00'),
  1041. ('project', 'closedDate', 'datetime', '', '关闭日期', 'input', '', '', '', '', '', 20, 0, 0, '0', '0', '0', '1', 1, '', '', '2021-07-28 16:54:38', '', '0000-00-00 00:00:00'),
  1042. ('project', 'canceledBy', 'varchar', '30', '由谁取消', 'select', '', 'user', '', '', '', 21, 0, 0, '0', '0', '0', '1', 1, '', '', '2021-07-28 16:54:38', '', '0000-00-00 00:00:00'),
  1043. ('project', 'canceledDate', 'datetime', '', '取消日期', 'input', '', '', '', '', '', 22, 0, 0, '0', '0', '0', '1', 1, '', '', '2021-07-28 16:54:38', '', '0000-00-00 00:00:00'),
  1044. ('project', 'PO', 'varchar', '30', 'PO', 'select', '', 'user', '', '', '', 23, 0, 0, '0', '0', '0', '1', 1, '', '', '2021-07-28 16:54:38', '', '0000-00-00 00:00:00'),
  1045. ('project', 'PM', 'varchar', '30', '负责人', 'select', '', 'user', '', '', '', 24, 0, 0, '0', '0', '0', '1', 1, '', '', '2021-07-28 16:54:38', '', '0000-00-00 00:00:00'),
  1046. ('project', 'QD', 'varchar', '30', 'QD', 'select', '', 'user', '', '', '', 25, 0, 0, '0', '0', '0', '1', 1, '', '', '2021-07-28 16:54:38', '', '0000-00-00 00:00:00'),
  1047. ('project', 'RD', 'varchar', '30', 'RD', 'select', '', 'user', '', '', '', 26, 0, 0, '0', '0', '0', '1', 1, '', '', '2021-07-28 16:54:38', '', '0000-00-00 00:00:00'),
  1048. ('project', 'team', 'varchar', '90', '团队名称', 'input', '', '', '', '', '', 27, 0, 0, '0', '0', '0', '1', 1, '', '', '2021-07-28 16:54:38', '', '0000-00-00 00:00:00'),
  1049. ('project', 'acl', 'enum', '', '访问控制', 'select', '', '18', 'open', '', '', 28, 0, 0, '0', '0', '0', '1', 1, '', '', '2021-07-28 16:54:38', '', '0000-00-00 00:00:00'),
  1050. ('project', 'whitelist', 'text', '', '项目白名单', 'select', '', '7', '', '', '', 29, 0, 0, '0', '0', '0', '1', 1, '', '', '2021-07-28 16:54:38', '', '0000-00-00 00:00:00'),
  1051. ('project', 'order', 'mediumint', '8', '排序', 'input', '', '', '', '', '', 30, 0, 0, '0', '0', '0', '1', 1, '', '', '2021-07-28 16:54:38', '', '0000-00-00 00:00:00'),
  1052. ('project', 'deleted', 'enum', '', '已删除', 'select', '', '[\"\\u672a\\u5220\\u9664\",\"\\u5df2\\u5220\\u9664\"]', '0', '', '', 31, 0, 0, '0', '0', '0', '1', 1, '', '', '2021-07-28 16:54:38', '', '0000-00-00 00:00:00')");
  1053. }
  1054. }
  1055. /**
  1056. * Add file fields.
  1057. *
  1058. * @access public
  1059. * @return bool
  1060. */
  1061. public function addFileFields()
  1062. {
  1063. $layoutModules = $this->dao->select('DISTINCT module')->from(TABLE_WORKFLOWLAYOUT)->where('field')->eq('file')->fetchPairs();
  1064. $relationModules = $this->dao->select('DISTINCT prev')->from(TABLE_WORKFLOWRELATIONLAYOUT)->where('field')->eq('file')->fetchPairs();
  1065. $modules = arrayUnion($layoutModules, $relationModules);
  1066. if(!$modules) return true;
  1067. $fileFields = $this->dao->select('*')->from(TABLE_WORKFLOWFIELD)->where('module')->in($modules)->andWhere('control')->eq('file')->andWhere('field')->eq('file')->fetchGroup('module', 'field');
  1068. $file = new stdclass();
  1069. $file->field = 'file';
  1070. $file->type = 'varchar';
  1071. $file->length = '255';
  1072. $file->name = $this->lang->files;
  1073. $file->control = 'file';
  1074. $file->options = '[]';
  1075. foreach($modules as $module)
  1076. {
  1077. if(isset($fileFields[$module]['file'])) continue;
  1078. $file->module = $module;
  1079. $this->dao->delete()->from(TABLE_WORKFLOWFIELD)->where('module')->eq($module)->andWhere('field')->eq('file')->exec();
  1080. $this->dao->insert(TABLE_WORKFLOWFIELD)->data($file)->exec();
  1081. }
  1082. return true;
  1083. }
  1084. /**
  1085. * Process feedback field.
  1086. *
  1087. * @access public
  1088. * @return void
  1089. */
  1090. public function processFeedbackField()
  1091. {
  1092. /* If feedback's closed reason is totask/tostory/tobug, change it to solution and set closed reason commented.*/
  1093. $feedbacks = $this->dao->select('id, closedReason')->from(TABLE_FEEDBACK)->where('deleted')->eq('0')->fetchAll();
  1094. foreach($feedbacks as $feedback)
  1095. {
  1096. $feedback->closedReason = strtolower($feedback->closedReason);
  1097. if(in_array($feedback->closedReason, array('totask', 'tobug', 'totask', 'totodo')))
  1098. {
  1099. $this->dao->update(TABLE_FEEDBACK)
  1100. ->set('solution')->eq($feedback->closedReason)
  1101. ->set('closedReason')->eq('commented')
  1102. ->where('id')->eq($feedback->id)
  1103. ->exec();
  1104. }
  1105. }
  1106. /* Process actions. */
  1107. $this->dao->update(TABLE_ACTION)->set('extra')->eq('commented')
  1108. ->where('objectType')->eq('feedback')
  1109. ->andWhere('action')->eq('closed')
  1110. ->andWhere('(extra')->eq('ToStory')
  1111. ->orWhere('extra')->eq('ToBug')
  1112. ->orWhere('extra')->eq('ToTask')
  1113. ->orWhere('extra')->eq('ToTodo')
  1114. ->markRight(1)
  1115. ->exec();
  1116. }
  1117. /**
  1118. * Add report actions.
  1119. *
  1120. * @access public
  1121. * @return bool
  1122. */
  1123. public function addReportActions()
  1124. {
  1125. $this->loadModel('workflowaction');
  1126. $actionCode = 'report';
  1127. $actionLang = $this->lang->workflowaction->default;
  1128. $actionConfig = $this->config->workflowaction->default;
  1129. $flows = $this->dao->select('module')->from(TABLE_WORKFLOW)->where('type')->eq('flow')->andWhere('buildin')->eq(0)->fetchPairs();
  1130. $actions = $this->dao->select('module')->from(TABLE_WORKFLOWACTION)->where('action')->eq($actionCode)->fetchPairs();
  1131. $action = new stdclass();
  1132. $action->action = $actionCode;
  1133. $action->name = $actionLang->actions[$actionCode];
  1134. $action->type = zget($actionConfig->types, $actionCode, 'single');
  1135. $action->batchMode = zget($actionConfig->batchModes, $actionCode, 'different');
  1136. $action->open = $actionConfig->opens[$actionCode];
  1137. $action->position = $actionConfig->positions[$actionCode];
  1138. $action->show = 'direct';
  1139. $action->createdBy = isset($this->app->user->account) ? $this->app->user->account : 'admin';
  1140. $action->createdDate = helper::now();
  1141. foreach($flows as $module)
  1142. {
  1143. if(isset($actions[$module])) continue;
  1144. $action->module = $module;
  1145. $this->dao->delete()->from(TABLE_WORKFLOWACTION)->where('module')->eq($module)->andWhere('action')->eq($actionCode)->andWhere('vision')->eq('rnd')->exec();
  1146. $this->dao->insert(TABLE_WORKFLOWACTION)->data($action)->autoCheck()->exec();
  1147. }
  1148. return !dao::isError();
  1149. }
  1150. /**
  1151. * Process view fields.
  1152. *
  1153. * @access public
  1154. * @return bool
  1155. */
  1156. public function processViewFields()
  1157. {
  1158. $datasources = $this->dao->select('id, datasource, keyField, valueField')->from(TABLE_WORKFLOWDATASOURCE)->where('view')->ne('')->andWhere('buildin')->eq('0')->fetchAll();
  1159. foreach($datasources as $datasource)
  1160. {
  1161. try
  1162. {
  1163. $tmpView = 'view_datasource_tmp';
  1164. $sqls = array();
  1165. $sqls[] = "DROP VIEW IF EXISTS $tmpView";
  1166. $sqls[] = "CREATE VIEW $tmpView AS $datasource->datasource";
  1167. foreach($sqls as $sql) $this->dbh->query($sql);
  1168. $sqlFields = $this->dbh->query("DESC $tmpView")->fetchAll();
  1169. $i = 1;
  1170. $fields = array();
  1171. foreach($sqlFields as $field)
  1172. {
  1173. $fields[$field->Field] = "field{$i}";;
  1174. $i++;
  1175. }
  1176. $sql = "DROP VIEW $tmpView";
  1177. $this->dbh->query($sql);
  1178. $viewFields = implode(',', $fields);
  1179. $view = "view_datasource_{$datasource->id}";
  1180. $sqls = array();
  1181. $sqls[] = "DROP VIEW IF EXISTS $view";
  1182. $sqls[] = "CREATE VIEW $view ($viewFields) AS $datasource->datasource";
  1183. foreach($sqls as $sql) $this->dbh->query($sql);
  1184. $keyField = zget($fields, $datasource->keyField);
  1185. $valueField = zget($fields, $datasource->valueField);
  1186. $this->dao->update(TABLE_WORKFLOWDATASOURCE)->set('keyField')->eq($keyField)->set('valueField')->eq($valueField)->where('id')->eq($datasource->id)->exec();
  1187. }
  1188. catch(PDOException $exception)
  1189. {
  1190. dao::$errors = $exception->getMessage();
  1191. return false;
  1192. }
  1193. }
  1194. }
  1195. /**
  1196. * Process flow position.
  1197. *
  1198. * @access public
  1199. * @return void
  1200. */
  1201. public function processFlowPosition()
  1202. {
  1203. $customPrimaryFlows = $this->dao->select('module')->from(TABLE_WORKFLOW)
  1204. ->where('buildin')->eq(0)
  1205. ->andWhere('type')->eq('flow')
  1206. ->andWhere('status')->eq('normal')
  1207. ->andWhere('navigator')->eq('primary')
  1208. ->fetchPairs('module', 'module');
  1209. $flows = $this->dao->select('id,app,position,module')->from(TABLE_WORKFLOW)
  1210. ->where('buildin')->eq(0)
  1211. ->andWhere('type')->eq('flow')
  1212. ->andWhere('app')->in($customPrimaryFlows)
  1213. ->andWhere('status')->eq('normal')
  1214. ->andWhere('navigator')->eq('secondary')
  1215. ->fetchAll();
  1216. foreach($flows as $flow)
  1217. {
  1218. $direction = strpos($flow->position, 'after') === 0 ? 'after' : 'before';
  1219. $position = substr($flow->position, strlen($direction));
  1220. if(preg_match('/^browse(\d+)/', $position))
  1221. {
  1222. $position = $direction . $flow->app;
  1223. $this->dao->update(TABLE_WORKFLOW)->set('position')->eq($position)->where('id')->eq($flow->id)->exec();
  1224. }
  1225. }
  1226. }
  1227. /**
  1228. * 处理工作流内置模块的列表字段。
  1229. * Process buildin browse fields.
  1230. *
  1231. * @access public
  1232. * @return void
  1233. */
  1234. public function processBuildinBrowseFields()
  1235. {
  1236. $fieldGroup = $this->dao->select('t1.module, t1.field')->from(TABLE_WORKFLOWFIELD)->alias('t1')
  1237. ->leftJoin(TABLE_WORKFLOW)->alias('t2')->on('t1.module = t2.module')
  1238. ->where('t2.buildin')->eq('1')
  1239. ->andWhere('t1.role')->eq('custom')
  1240. ->fetchGroup('module', 'field');
  1241. $layout = new stdclass();
  1242. $layout->ui = 0;
  1243. foreach($fieldGroup as $module => $fields)
  1244. {
  1245. $method = 'browse';
  1246. if($module == 'product' || $module == 'execution')
  1247. {
  1248. $method = 'all';
  1249. }
  1250. else if($module == 'story')
  1251. {
  1252. $module = 'product';
  1253. }
  1254. else if($module == 'feedback')
  1255. {
  1256. $method = 'admin';
  1257. }
  1258. else if($module == 'task')
  1259. {
  1260. $module = 'execution';
  1261. $method = 'task';
  1262. }
  1263. else if($module == 'build')
  1264. {
  1265. $module = 'execution';
  1266. $method = 'build';
  1267. }
  1268. /* 如果内置模块的字段扩展过,则将该模块的列表动作设置成扩展。 */
  1269. $this->dao->update(TABLE_WORKFLOWACTION)->set('extensionType')->eq('extend')->where('module')->eq($module)->andWhere('action')->eq($method)->exec();
  1270. /* 将内置模块新增的字段插入到列表页的layout表。 */
  1271. $visions = $this->dao->select('vision')->from(TABLE_WORKFLOWACTION)->where('module')->eq($module)->andWhere('action')->eq($method)->fetchPairs();
  1272. $this->dao->delete()->from(TABLE_WORKFLOWLAYOUT)->where('module')->eq($module)->andWhere('action')->eq($method)->andWhere('ui')->eq(0)->andWhere('field')->in(array_keys($fields))->andWhere('vision')->in($visions)->exec();
  1273. $layout->order = 1;
  1274. $layout->module = $module;
  1275. $layout->action = $method;
  1276. foreach($visions as $vision)
  1277. {
  1278. $layout->vision = $vision;
  1279. foreach($fields as $field)
  1280. {
  1281. $layout->field = $field->field;
  1282. $this->dao->insert(TABLE_WORKFLOWLAYOUT)->data($layout)->exec();
  1283. $layout->order ++;
  1284. }
  1285. }
  1286. }
  1287. }
  1288. }