model.php 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521
  1. <?php
  2. /**
  3. * The view file of datatable module of ZenTaoPMS.
  4. *
  5. * @copyright Copyright 2014-2014 禅道软件(青岛)有限公司(ZenTao Software (Qingdao) Co., Ltd. www.cnezsoft.com)
  6. * @license business(商业软件)
  7. * @author Hao sun <sunhao@cnezsoft.com>
  8. * @package datatable
  9. * @version $Id$
  10. * @link https://www.zentao.net
  11. */
  12. ?>
  13. <?php
  14. class datatableModel extends model
  15. {
  16. /**
  17. * 获取列表字段的基本配置信息。
  18. * Get field list.
  19. *
  20. * @param string $module
  21. * @param string $method
  22. * @access public
  23. * @return array
  24. */
  25. public function getFieldList($module, $method = '')
  26. {
  27. /* Load corresponding module. */
  28. if(!isset($this->config->$module)) $this->loadModel($module);
  29. $config = isset($this->config->$module) ? $this->config->$module : new stdclass();
  30. if(!empty($method) && isset($config->$method) && isset($config->$method->dtable)) $config = $config->$method;
  31. $fieldList = isset($config->dtable->fieldList) ? $config->dtable->fieldList : array();
  32. /* If doesn't need product, remove 'product' field. */
  33. if($this->session->hasProduct == 0 && (strpos($this->config->datatable->noProductModule, ",$module,") !== false))
  34. {
  35. $productIndex = array_search('product', $config->dtable->defaultField);
  36. if($productIndex) unset($config->dtable->defaultField[$productIndex]);
  37. if(isset($fieldList['product'])) unset($fieldList['product']);
  38. }
  39. /* Nomal product without 'branch' field. */
  40. if($this->session->currentProductType === 'normal') unset($config->fieldList['branch'], $config->fieldList['branchName']);
  41. foreach($fieldList as $fieldName => $items)
  42. {
  43. /* Translate field title. */
  44. if(!isset($items['title'])) $items['title'] = $fieldName;
  45. $title = zget($this->lang->$module, $items['title'], zget($this->lang, $items['title'], $items['title']));
  46. $fieldList[$fieldName]['title'] = $title;
  47. /* Set col config default value. */
  48. if(!empty($items['type']) && isset($this->config->datatable->defaultColConfig[$items['type']]))
  49. {
  50. $fieldList[$fieldName] = array_merge($this->config->datatable->defaultColConfig[$items['type']], $fieldList[$fieldName]);
  51. }
  52. }
  53. /* 加载工作流字段配置。 */
  54. if($this->config->edition != 'open') $fieldList += $this->appendWorkflowFields($module, $method);
  55. return $fieldList;
  56. }
  57. /**
  58. * 获取列表显示的字段信息。
  59. * Get save setting field.
  60. *
  61. * @param string $module
  62. * @param string $method
  63. * @param bool $showAll
  64. * @param string $extra
  65. * @access public
  66. * @return array
  67. */
  68. public function getSetting($module, $method = '', $showAll = false, $extra = '')
  69. {
  70. if(!$method) $method = $this->app->getMethodName();
  71. $datatableId = $module . ucfirst($method);
  72. /* Split story,requirement and epic custom fields. */
  73. if(("$module-$method" == 'product-browse') && in_array($extra, array('story', 'requirement', 'epic'))) $datatableId .= ucfirst($extra);
  74. $module = zget($this->config->datatable->moduleAlias, "$module-$method", $module);
  75. if($module == 'story' && $extra && $module != $extra) $module = $extra;
  76. if(!isset($this->config->$module)) $this->loadModel($module);
  77. if(isset($this->config->datatable->$datatableId->cols)) $setting = json_decode($this->config->datatable->$datatableId->cols, true);
  78. $fieldList = $this->getFieldList($module, $method);
  79. $fieldSetting = array();
  80. foreach($fieldList as $field => $fieldConfig)
  81. {
  82. if(isset($setting[$field]))
  83. {
  84. $fieldSetting[$field] = $setting[$field];
  85. continue;
  86. }
  87. $fieldSetting[$field] = $fieldConfig;
  88. }
  89. if(empty($fieldSetting))
  90. {
  91. $fieldSetting = $this->formatFields($module, $fieldList, !$showAll);
  92. }
  93. else
  94. {
  95. $order = 0;
  96. foreach($fieldSetting as $field => $set)
  97. {
  98. if(!$showAll && empty($set['required']) && empty($set['show']))
  99. {
  100. unset($fieldSetting[$field]);
  101. continue;
  102. }
  103. if(isset($set['display']) && $set['display'] === false)
  104. {
  105. unset($fieldSetting[$field]);
  106. continue;
  107. }
  108. if($this->session->currentProductType === 'normal' && in_array($field, array('branch', 'branchName')))
  109. {
  110. unset($fieldSetting[$field]);
  111. continue;
  112. }
  113. if(isset($fieldList[$field]))
  114. {
  115. foreach($fieldList[$field] as $key => $value)
  116. {
  117. if(!isset($set[$key])) $fieldSetting[$field][$key] = $value;
  118. }
  119. }
  120. if(!isset($set['name'])) $fieldSetting[$field]['name'] = $field;
  121. if($module == 'testcase' && $field == 'id') $fieldSetting[$field]['name'] = 'caseID';
  122. if($field == 'actions' && empty($fieldSetting[$field]['width'])) $fieldSetting[$field]['width'] = $fieldList[$field]['width'];
  123. if(!isset($set['order'])) $fieldSetting[$field]['order'] = $order;
  124. $order++;
  125. }
  126. if(in_array($module, array('product', 'project', 'execution')) and empty($this->config->setCode)) unset($fieldSetting['code']);
  127. if($module == 'story' && $method == 'browse' && $this->app->tab == 'project')
  128. {
  129. $project = $this->loadModel('project')->getByID((int)$this->session->project);
  130. $projectModel = $project->model;
  131. if(($projectModel == 'waterfall' || $projectModel == 'waterfallplus') && isset($fieldSetting['plan']))
  132. {
  133. unset($fieldSetting['plan']);
  134. }
  135. }
  136. }
  137. uasort($fieldSetting, array('datatableModel', 'sortCols'));
  138. return $fieldSetting;
  139. }
  140. /**
  141. * Get field list.
  142. *
  143. * @param string $module
  144. * @access public
  145. * @return array
  146. */
  147. public function getOldFieldList($module)
  148. {
  149. if(!isset($this->config->$module)) $this->loadModel($module);
  150. if($this->session->hasProduct == 0 and (strpos($this->config->datatable->noProductModule, ",$module,") !== false))
  151. {
  152. $productIndex = array_search('product', $this->config->$module->datatable->defaultField);
  153. if($productIndex) unset($this->config->$module->datatable->defaultField[$productIndex]);
  154. if(isset($this->config->$module->datatable->fieldList['product'])) unset($this->config->$module->datatable->fieldList['product']);
  155. }
  156. if($this->session->currentProductType === 'normal') unset($this->config->$module->datatable->fieldList['branch']);
  157. foreach($this->config->$module->datatable->fieldList as $field => $items)
  158. {
  159. if($field === 'branch')
  160. {
  161. if($this->session->currentProductType === 'branch') $this->config->$module->datatable->fieldList[$field]['title'] = $this->lang->datatable->branch;
  162. if($this->session->currentProductType === 'platform') $this->config->$module->datatable->fieldList[$field]['title'] = $this->lang->datatable->platform;
  163. continue;
  164. }
  165. $title = zget($this->lang->$module, $items['title'], zget($this->lang, $items['title'], $items['title']));
  166. $this->config->$module->datatable->fieldList[$field]['title'] = $title;
  167. }
  168. if($this->config->edition != 'open')
  169. {
  170. $fields = $this->loadModel('workflowfield')->getList($module);
  171. foreach($fields as $field)
  172. {
  173. if($field->buildin) continue;
  174. $this->config->$module->datatable->fieldList[$field->field]['title'] = $field->name;
  175. $this->config->$module->datatable->fieldList[$field->field]['width'] = '120';
  176. $this->config->$module->datatable->fieldList[$field->field]['type'] = 'html';
  177. $this->config->$module->datatable->fieldList[$field->field]['fixed'] = 'no';
  178. $this->config->$module->datatable->fieldList[$field->field]['required'] = 'no';
  179. }
  180. }
  181. return $this->config->$module->datatable->fieldList;
  182. }
  183. /**
  184. * Get save setting field.
  185. *
  186. * @param string $module
  187. * @access public
  188. * @return object
  189. */
  190. public function getOldSetting($module)
  191. {
  192. $method = $this->app->getMethodName();
  193. $datatableId = $module . ucfirst($method);
  194. $mode = isset($this->config->datatable->$datatableId->mode) ? $this->config->datatable->$datatableId->mode : 'table';
  195. $key = $mode == 'datatable' ? 'cols' : 'tablecols';
  196. $module = zget($this->config->datatable->moduleAlias, "$module-$method", $module);
  197. if(!isset($this->config->$module)) $this->loadModel($module);
  198. if(isset($this->config->datatable->$datatableId->$key)) $setting = json_decode($this->config->datatable->$datatableId->$key);
  199. $fieldList = $this->getOldFieldList($module);
  200. if(empty($setting))
  201. {
  202. $setting = $this->config->$module->datatable->defaultField;
  203. $order = 1;
  204. foreach($setting as $key => $value)
  205. {
  206. $id = $value;
  207. $set = new stdclass();;
  208. $set->order = $order++;
  209. $set->id = $id;
  210. $set->show = true;
  211. $set->width = $fieldList[$id]['width'];
  212. $set->fixed = $fieldList[$id]['fixed'];
  213. $set->title = $fieldList[$id]['title'];
  214. $set->sort = isset($fieldList[$id]['sort']) ? $fieldList[$id]['sort'] : 'yes';
  215. $set->name = isset($fieldList[$id]['name']) ? $fieldList[$id]['name'] : '';
  216. if(isset($fieldList[$id]['minWidth'])) $set->minWidth = $fieldList[$id]['minWidth'];
  217. if(isset($fieldList[$id]['maxWidth'])) $set->maxWidth = $fieldList[$id]['maxWidth'];
  218. if(isset($fieldList[$id]['pri'])) $set->pri = $fieldList[$id]['pri'];
  219. $setting[$key] = $set;
  220. }
  221. }
  222. else
  223. {
  224. foreach($setting as $key => $set)
  225. {
  226. if(!isset($fieldList[$set->id]))
  227. {
  228. unset($setting[$key]);
  229. continue;
  230. }
  231. if($this->session->currentProductType === 'normal' and $set->id === 'branch')
  232. {
  233. unset($setting[$key]);
  234. continue;
  235. }
  236. if($set->id == 'actions') $set->width = $fieldList[$set->id]['width'];
  237. $set->title = $fieldList[$set->id]['title'];
  238. $set->sort = isset($fieldList[$set->id]['sort']) ? $fieldList[$set->id]['sort'] : 'yes';
  239. }
  240. }
  241. usort($setting, array('datatableModel', 'sortOldCols'));
  242. return $setting;
  243. }
  244. /**
  245. * 获取期望的配置项。
  246. * Format fields by config.
  247. *
  248. * @param string $module
  249. * @param array $fieldList
  250. * @param bool $onlyshow
  251. * @access public
  252. * @return array
  253. */
  254. public function formatFields($module, $fieldList, $onlyshow = true)
  255. {
  256. $this->app->loadLang($module);
  257. $setting = array();
  258. $order = 1;
  259. foreach($fieldList as $field => $config)
  260. {
  261. if((isset($config['display']) && !$config['display']) || (empty($config['required']) && empty($config['show']) && $onlyshow)) continue;
  262. $config['order'] = $order++;
  263. $config['id'] = $field;
  264. $config['show'] = !empty($config['show']);
  265. $config['sortType'] = !empty($config['sortType']);
  266. $config['title'] = zget($config, 'title', zget($this->lang->$module, $field, zget($this->lang, $field)));
  267. $config['name'] = zget($config, 'name', $field);
  268. $config['type'] = zget($config, 'type', 'text');
  269. $config['width'] = zget($config, 'width', '');
  270. $config['fixed'] = zget($config, 'fixed', '');
  271. $config['link'] = zget($config, 'link', '');
  272. $config['group'] = zget($config, 'group', '');
  273. $setting[$field] = $config;
  274. }
  275. return $setting;
  276. }
  277. /**
  278. * 字段排序规则。
  279. * Sort cols.
  280. *
  281. * @param array $a
  282. * @param array $b
  283. * @static
  284. * @access public
  285. * @return int
  286. */
  287. public static function sortCols($a, $b)
  288. {
  289. if(!isset($a['order']) or !isset($b['order'])) return 0;
  290. return $a['order'] - $b['order'];
  291. }
  292. /**
  293. * Sort old cols.
  294. *
  295. * @param object $a
  296. * @param object $b
  297. * @static
  298. * @access public
  299. * @return int
  300. */
  301. public static function sortOldCols($a, $b)
  302. {
  303. if(!isset($a->order)) return 0;
  304. return $a->order - $b->order;
  305. }
  306. /**
  307. * 打印表格标题。
  308. * Print table head.
  309. *
  310. * @param object $col
  311. * @param string $orderBy
  312. * @param string $vars
  313. * @param bool $checkBox
  314. * @access public
  315. * @return void
  316. */
  317. public function printHead($col, $orderBy, $vars, $checkBox = true)
  318. {
  319. $id = $col->id;
  320. if($col->show)
  321. {
  322. $fixed = zget($col, 'fixed', 'no') == 'no' ? 'true' : 'false';
  323. $width = is_numeric($col->width) ? "{$col->width}px" : $col->width;
  324. $title = isset($col->title) ? "title='$col->title'" : '';
  325. $title = (isset($col->name) and $col->name) ? "title='$col->name'" : $title;
  326. if($id == 'id' and (int)$width < 90) $width = '90px';
  327. $align = $id == 'actions' ? 'text-center' : '';
  328. $align = in_array($id, array('budget', 'teamCount', 'estimate', 'consume', 'consumed', 'left')) ? 'text-right' : $align;
  329. $style = '';
  330. $data = '';
  331. $data .= "data-width='$width'";
  332. $style .= "width:$width;";
  333. if(isset($col->minWidth))
  334. {
  335. $data .= "data-minWidth='{$col->minWidth}px'";
  336. $style .= "min-width:{$col->minWidth}px;";
  337. }
  338. if(isset($col->maxWidth))
  339. {
  340. $data .= "data-maxWidth='{$col->maxWidth}px'";
  341. $style .= "max-width:{$col->maxWidth}px;";
  342. }
  343. if(isset($col->pri)) $data .= "data-pri='{$col->pri}'";
  344. echo "<th data-flex='$fixed' $data style='$style' class='c-$id $align' $title>";
  345. if($id == 'actions')
  346. {
  347. echo $this->lang->actions;
  348. }
  349. elseif(isset($col->sort) and $col->sort == 'no')
  350. {
  351. echo $col->title;
  352. }
  353. else
  354. {
  355. if($id == 'id' && $checkBox) echo "<div class='checkbox-primary check-all' title='{$this->lang->selectAll}'><label></label></div>";
  356. common::printOrderLink($id, $orderBy, $vars, $col->title);
  357. }
  358. echo '</th>';
  359. }
  360. }
  361. /**
  362. * Set fixed field width
  363. *
  364. * @param array $setting
  365. * @param int $minLeftWidth
  366. * @param int $minRightWidth
  367. * @access public
  368. * @return array
  369. */
  370. public function setFixedFieldWidth($setting, $minLeftWidth = 550, $minRightWidth = 140)
  371. {
  372. $widths['leftWidth'] = 30;
  373. $widths['rightWidth'] = 0;
  374. $hasLeftAuto = false;
  375. $hasRightAuto = false;
  376. foreach($setting as $key => $value)
  377. {
  378. if($value->fixed != 'no')
  379. {
  380. if($value->fixed == 'left' and $value->width == 'auto') $hasLeftAuto = true;
  381. if($value->fixed == 'right' and $value->width == 'auto') $hasRightAuto = true;
  382. $widthKey = $value->fixed . 'Width';
  383. if(!isset($widths[$widthKey])) $widths[$widthKey] = 0;
  384. $widths[$widthKey] += (int)trim($value->width, 'px');
  385. }
  386. }
  387. if($widths['leftWidth'] <= 550 and $hasLeftAuto) $widths['leftWidth'] = 550;
  388. if($widths['rightWidth'] <= 0 and $hasRightAuto) $widths['rightWidth'] = 140;
  389. return $widths;
  390. }
  391. /**
  392. * 加载工作流字段配置到数据表字段配置中。
  393. * Load workflow fields.
  394. *
  395. * @param string $module
  396. * @param string $method
  397. * @access public
  398. * @return array
  399. */
  400. public function appendWorkflowFields($module, $method)
  401. {
  402. if($module == 'build' && $method == 'build')
  403. {
  404. $module = 'build';
  405. $method = 'browse'; // 版本加载build-browse的layout配置。
  406. }
  407. elseif($module == 'task' && $method == 'task')
  408. {
  409. $method = 'browse'; // 任务加载task-browse的layout配置。
  410. }
  411. elseif($module == 'bug' && $method == 'bug')
  412. {
  413. $method = 'browse'; // 执行bug列表加载bug-browse的layout配置。
  414. }
  415. elseif($module == 'story' && $method == 'story')
  416. {
  417. $method = 'browse'; // 执行需求列表加载story-browse的layout配置。
  418. }
  419. elseif($module == 'testcase' && $method == 'testcase')
  420. {
  421. $method = 'browse'; // 执行用例列表加载testcase-browse的layout配置。
  422. }
  423. elseif($module == 'projectrelease')
  424. {
  425. $module = 'release'; // 项目发布加载release-browse的layout配置。
  426. }
  427. $this->loadModel('workflow');
  428. $this->loadModel('workflowgroup');
  429. $this->loadModel('workflowaction');
  430. if(($this->app->tab == 'project' || $this->app->tab == 'execution') && in_array($module, $this->config->workflowgroup->modules['product']))
  431. {
  432. $groupIdList = array();
  433. $fields = array();
  434. $projectID = $this->app->tab == 'execution' ? $this->session->execution : $this->session->project;
  435. $products = $this->dao->select('t2.*')->from(TABLE_PROJECTPRODUCT)->alias('t1')
  436. ->leftJoin(TABLE_PRODUCT)->alias('t2')->on('t1.product = t2.id')
  437. ->where('t1.project')->eq((int)$projectID)
  438. ->fetchAll('id');
  439. foreach($products as $product) $groupIdList[] = $product->workflowGroup;
  440. foreach(array_unique($groupIdList) as $groupID)
  441. {
  442. $flow = $this->workflow->getByModule($module, false, $groupID);
  443. if(empty($flow)) continue;
  444. if($groupID != $flow->group) $groupID = 0;
  445. if($flow->buildin)
  446. {
  447. $action = $this->workflowaction->getByModuleAndAction($module, $method, $groupID);
  448. if(!$action || (isset($action->extensionType) && $action->extensionType != 'extend')) continue; // 不扩展不追加字段。
  449. }
  450. $fields += $this->workflowaction->getPageFields($module, $method, true, array(), 0, $groupID);
  451. }
  452. }
  453. else
  454. {
  455. $groupID = $this->workflowgroup->getGroupIDBySession($module);
  456. $flow = $this->workflow->getByModule($module, false, $groupID);
  457. if(empty($flow)) return [];
  458. if($groupID != $flow->group) $groupID = 0;
  459. if($flow->buildin)
  460. {
  461. $action = $this->workflowaction->getByModuleAndAction($module, $method, $groupID);
  462. if(!$action || (isset($action->extensionType) && $action->extensionType != 'extend')) return []; // 不扩展不追加字段。
  463. }
  464. $fields = $this->workflowaction->getPageFields($module, $method, true, array(), 0, $groupID);
  465. }
  466. return $this->loadModel('flow')->buildDtableCols($fields, [], [], isset($flow->buildin) && !$flow->buildin);
  467. }
  468. }