tao.php 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285
  1. <?php
  2. /**
  3. * The zen file of transfer module of ZenTaoPMS.
  4. *
  5. * @copyright Copyright 2009-2023 禅道软件(青岛)有限公司(ZenTao Software (Qingdao) Co., Ltd. www.zentao.net)
  6. * @license ZPL(https://zpl.pub/page/zplv12.html) or AGPL(https://www.gnu.org/licenses/agpl-3.0.en.html)
  7. * @author Tang Hucheng<tanghucheng@easycorp.ltd>
  8. * @package transfer
  9. * @link https://www.zentao.net
  10. */
  11. class transferTao extends transferModel
  12. {
  13. /**
  14. * 根据config:dataSource中配置的方法获取字段数据源。
  15. * Get source by module method.
  16. *
  17. * @param string $module
  18. * @param string $callModule
  19. * @param string $method
  20. * @param string|array|int $params
  21. * @param string|array $pairs
  22. * @access protected
  23. * @return array
  24. */
  25. protected function getSourceByModuleMethod($module, $callModule, $method, $params = '', $pairs = '')
  26. {
  27. /* 获取模块传递的参数。 */
  28. /* Get params. */
  29. $getParams = $this->session->{$module . 'TransferParams'};
  30. /* 解析dataSource params中配置的参数。 */
  31. /* Parse params. */
  32. if(is_string($params)) $params = explode('&', $params);
  33. foreach($params as $param => $value)
  34. {
  35. /* 如果参数是$开头的变量,则从SESSION中获取该变量。 */
  36. /* If the param is $var, get it from SESSION. */
  37. if(!is_string($value)) continue;
  38. if(strpos($value, '$') === false) continue;
  39. $params[$param] = isset($getParams[ltrim($value, '$')]) ? $getParams[ltrim($value, '$')] : '';
  40. if(isset($this->config->transfer->convertInt[$callModule][$method][ltrim($value, '$')])) $params[$param] = (int)$params[$param];
  41. if(isset($this->config->transfer->convertInt[$callModule][$method][$param])) $params[$param] = (int)$params[$param];
  42. }
  43. /* 调用模块的方法。 */
  44. /* If this method has multiple parameters use call_user_func_array. */
  45. if(is_array($params) and $params)
  46. {
  47. $values = call_user_func_array(array($this->loadModel($callModule), $method), $params);
  48. }
  49. else
  50. {
  51. $values = $this->loadModel($callModule)->$method($params);
  52. }
  53. /* 解析dataSource pairs中配置的参数(是否需要返回array(key => value)形式的关联数组。 */
  54. /* Parse pairs. */
  55. if(!empty($pairs))
  56. {
  57. $valuePairs = array();
  58. foreach($values as $key => $value)
  59. {
  60. if(is_object($value)) $value = get_object_vars($value);
  61. $valuePairs[$key] = $value[$pairs[1]];
  62. if(!empty($pairs[0])) $valuePairs[$value[$pairs[0]]] = $value[$pairs[1]];
  63. }
  64. $values = $valuePairs;
  65. }
  66. return $values;
  67. }
  68. /**
  69. * 根据id获取附件分组。
  70. * Get file group by id.
  71. *
  72. * @param string $module
  73. * @param array $idList
  74. * @access protected
  75. * @return array
  76. */
  77. protected function getFileGroups($module, $idList)
  78. {
  79. if(in_array($module, array('epic', 'requirement'))) $module = "{$module},story";
  80. return $this->dao->select('id, objectID, pathname, title')->from(TABLE_FILE)
  81. ->where('objectType')->in($module)
  82. ->beginIf($idList)->andWhere('objectID')->in($idList)->fi()
  83. ->andWhere('extra')->ne('editor')
  84. ->fetchGroup('objectID');
  85. }
  86. /**
  87. * 获取级联数据列表。
  88. * Get cascade list for export excel.
  89. *
  90. * @param string $module
  91. * @param array $lists
  92. * @access protected
  93. * @return array
  94. */
  95. protected function getCascadeList($module, $lists)
  96. {
  97. /* 如果没有配置config->cascade,则不需要进行级联操作。*/
  98. /* If has not cascade config, do not need to do cascade operation. */
  99. $this->commonActions($module);
  100. if(!isset($this->moduleConfig->cascade)) return $lists;
  101. $cascadeArray = $this->moduleConfig->cascade;
  102. foreach($cascadeArray as $field => $linkField)
  103. {
  104. $fieldName = $field . 'List';
  105. $linkFieldName = $linkField . 'List';
  106. $tmpFieldName = array();
  107. if(isset($_POST['cascade'][$field]))
  108. {
  109. if(is_array($_POST['cascade'][$field])) $lists[$fieldName] = $_POST['cascade'][$field];
  110. continue;
  111. }
  112. if(empty($lists[$fieldName]) || empty($lists[$linkFieldName])) continue;
  113. /* 根据字段名获取表名。*/
  114. /* Get table name by field name. */
  115. $table = zget($this->config->objectTables, $field, '');
  116. if(empty($table)) continue;
  117. /* 根据字段名获取关联数据。*/
  118. /* Get ID list by field name. */
  119. $fieldIDList = array_keys($lists[$fieldName]);
  120. $fieldDatas = $this->dao->select("id, $linkField")->from($table)->where('id')->in($fieldIDList)->fetchPairs();
  121. if(empty($fieldDatas)) continue;
  122. /* 将获取到的数据替换到lists中。*/
  123. /* Replace data to lists. */
  124. foreach($fieldDatas as $id => $linkFieldID)
  125. {
  126. $tmpFieldName[0][$id] = $tmpFieldName[$linkFieldID][$id] = $lists[$fieldName][$id];
  127. }
  128. $lists[$fieldName] = $tmpFieldName;
  129. }
  130. return $lists;
  131. }
  132. /**
  133. * 解析Excel中下拉框单元格的值。
  134. * Parse value of multiple dropdown cells.
  135. *
  136. * @param string $cellValue
  137. * @param string $field
  138. * @param array $values
  139. * @access protected
  140. * @return array
  141. */
  142. protected function extractElements($cellValue, $field, $values)
  143. {
  144. if(empty($values)) return $cellValue;
  145. /* 多行下拉框和单行下拉框都按照多行处理。*/
  146. /* Multiple dropdowns and single dropdowns are processed in multiple rows. */
  147. $cellValue = explode("\n", $cellValue);
  148. foreach($cellValue as &$value)
  149. {
  150. /* 解析下拉框的值value(#rawValue),提取rawValue。*/
  151. /* Parse dropdown values value(#rawValue) and extract rawValue. */
  152. if(strrpos($value, '(#') !== false)
  153. {
  154. $value = trim(substr($value, strrpos($value,'(#') + 2), ')');
  155. }
  156. else
  157. {
  158. /* 如果value在values中存在则在values中查找(一般为语言项)。*/
  159. /* If value exists in values, find it in values (usually as a language item). */
  160. $valueKey = array_search($value, $values);
  161. $value = $valueKey !== false ? $valueKey : $value;
  162. }
  163. }
  164. /* 过滤掉数组中的空值(null、空字符串、0等)以及值为字符串 '0' 的元素,只保留其他非空元素。*/
  165. /* Filter out empty values (null, empty string, 0, etc.) in the array and only keep other non-empty elements. */
  166. $cellValue = array_filter($cellValue, function($v) {return (empty($v) && $v == '0') || !empty($v);});
  167. return implode(',', $cellValue);
  168. }
  169. /**
  170. * 配置导入字段。
  171. * Config import fields.
  172. *
  173. * @param string $module
  174. * @access protected
  175. * @return array
  176. */
  177. protected function getImportFields($module = '')
  178. {
  179. $this->commonActions($module);
  180. $moduleLang = $this->moduleLang;
  181. $fields = explode(',', $this->moduleConfig->templateFields); // 获取导入模板字段
  182. array_unshift($fields, 'id');
  183. foreach($fields as $key => $fieldName)
  184. {
  185. /* 匹配语言项。 */
  186. /* Match language item. */
  187. $fieldName = trim($fieldName);
  188. $fields[$fieldName] = isset($moduleLang->$fieldName) ? $moduleLang->$fieldName : $fieldName;
  189. unset($fields[$key]);
  190. }
  191. /* 获取工作流扩展字段。*/
  192. /* Get workflow extend fields. */
  193. if($this->config->edition != 'open')
  194. {
  195. $appendFields = $this->loadModel('flow')->getExtendFields($module, 'showimport');
  196. foreach($appendFields as $appendField)
  197. {
  198. /* 不是内置字段并且在导入确认页面展示。 */
  199. /* Is not builtin field and show in import confirm page. */
  200. if(!$appendField->buildin and $appendField->show) $fields[$appendField->field] = $appendField->name;
  201. }
  202. }
  203. return $fields;
  204. }
  205. /**
  206. * 更新子数据。
  207. * Update children datas.
  208. *
  209. * @param array $datas
  210. * @access protected
  211. * @return array
  212. */
  213. protected function updateChildDatas($datas)
  214. {
  215. foreach($datas as $id => $data)
  216. {
  217. if(!empty($data->mode)) $datas[$id]->name = '[' . $this->lang->task->multipleAB . '] ' . $data->name; //任务类型(多人任务/单人任务)
  218. }
  219. /* 如果存在子数据,则将子数据插入到父数据之后。*/
  220. /* Move child data after parent data. */
  221. $children = array();
  222. $orphans = array();
  223. foreach($datas as $data)
  224. {
  225. $parentId = isset($data->parentId) ? $data->parentId : (isset($data->parent) ? $data->parent : 0);
  226. if($parentId != 0 && !isset($datas[$parentId]))
  227. {
  228. $orphans[] = $data;
  229. }
  230. else
  231. {
  232. if(!isset($children[$parentId])) $children[$parentId] = array();
  233. $children[$parentId][] = $data;
  234. }
  235. }
  236. if(empty($children)) return $datas;
  237. $buildTree = function($parentId) use (&$buildTree, &$children)
  238. {
  239. $result = array();
  240. if(isset($children[$parentId]))
  241. {
  242. foreach($children[$parentId] as $child)
  243. {
  244. $result[] = $child;
  245. $result = array_merge($result, $buildTree($child->id));
  246. }
  247. }
  248. return $result;
  249. };
  250. $tree = array_merge((array)$buildTree(0), $orphans);
  251. if(count($tree) != count($datas)) return $datas;
  252. return $tree;
  253. }
  254. }