control.php 110 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758
  1. <?php
  2. /**
  3. * The control file of doc module of ZenTaoPMS.
  4. *
  5. * @copyright Copyright 2009-2023 禅道软件(青岛)有限公司(ZenTao Software (Qingdao) Co., Ltd. www.cnezsoft.com)
  6. * @license ZPL(http://zpl.pub/page/zplv12.html) or AGPL(https://www.gnu.org/licenses/agpl-3.0.en.html)
  7. * @author Chunsheng Wang <chunsheng@cnezsoft.com>
  8. * @package doc
  9. * @version $Id: control.php 933 2010-07-06 06:53:40Z wwccss $
  10. * @link https://www.zentao.net
  11. */
  12. class doc extends control
  13. {
  14. /**
  15. * @var \docModel
  16. */
  17. public $doc;
  18. /**
  19. * 构造函数,加载通用模块。
  20. * Construct function, load user, tree, action auto.
  21. *
  22. * @access public
  23. * @return void
  24. */
  25. public function __construct($moduleName = '', $methodName = '')
  26. {
  27. parent::__construct($moduleName, $methodName);
  28. $this->loadModel('user');
  29. $this->loadModel('tree');
  30. $this->loadModel('action');
  31. $this->loadModel('product');
  32. $this->loadModel('project');
  33. $this->loadModel('execution');
  34. }
  35. /**
  36. * 最近访问的空间首页。
  37. * Last viewed doc space home.
  38. *
  39. * @access public
  40. * @return void
  41. */
  42. public function lastViewedSpaceHome()
  43. {
  44. $lastViewedSpaceHome = $this->doc->getLastViewed('lastViewedSpaceHome');
  45. if($this->config->vision == 'lite' && $lastViewedSpaceHome == 'api') $lastViewedSpaceHome = 'mine';
  46. if($lastViewedSpaceHome === 'api') return $this->locate($this->createLink('api', 'index'));
  47. $spaceMap = array(
  48. 'mine' => 'mySpace',
  49. 'product' => 'productSpace',
  50. 'project' => 'projectSpace',
  51. 'custom' => 'teamSpace'
  52. );
  53. $method = $spaceMap[$lastViewedSpaceHome];
  54. if(empty($method)) return $this->locate($this->createLink('doc', 'mySpace'));
  55. return $this->locate($this->createLink('doc', $method));
  56. }
  57. /**
  58. * 最近访问的空间。
  59. * Last viewed doc space.
  60. *
  61. * @access public
  62. * @return void
  63. */
  64. public function lastViewedSpace()
  65. {
  66. $lastViewedSpaceHome = $this->doc->getLastViewed('lastViewedSpaceHome');
  67. if($this->config->vision == 'lite' && $lastViewedSpaceHome == 'api') $lastViewedSpaceHome = 'mine';
  68. if($lastViewedSpaceHome === 'api') return $this->locate($this->createLink('api', 'index'));
  69. $spaceMap = array(
  70. 'mine' => 'mySpace',
  71. 'product' => 'productSpace',
  72. 'project' => 'projectSpace',
  73. 'custom' => 'teamSpace'
  74. );
  75. $method = $spaceMap[$lastViewedSpaceHome];
  76. if(empty($method) || !common::hasPriv('doc', $method)) return $this->locate($this->createLink('doc', 'mySpace'));
  77. $lastViewedSpace = $this->doc->getLastViewed('lastViewedSpace');
  78. if(!is_numeric($lastViewedSpace)) return $this->locate($this->createLink('doc', 'mySpace'));
  79. return $this->locate($this->createLink('doc', $method, "objectID={$lastViewedSpace}"));
  80. }
  81. /**
  82. * 最近访问的库。
  83. * Last viewed doc lib.
  84. *
  85. * @access public
  86. * @return void
  87. */
  88. public function lastViewedLib()
  89. {
  90. $lastViewedSpaceHome = $this->doc->getLastViewed('lastViewedSpaceHome');
  91. $lastViewedLib = $this->doc->getLastViewed('lastViewedLib');
  92. if($lastViewedSpaceHome === 'api')
  93. {
  94. if(is_numeric($lastViewedLib)) return $this->locate($this->createLink('api', 'index', "libID={$lastViewedLib}"));
  95. return $this->locate($this->createLink('api', 'index'));
  96. }
  97. $lastViewedSpace = $this->doc->getLastViewed('lastViewedSpace');
  98. $spaceMap = array(
  99. 'mine' => 'mySpace',
  100. 'product' => 'productSpace',
  101. 'project' => 'projectSpace',
  102. 'custom' => 'teamSpace'
  103. );
  104. $method = $spaceMap[$lastViewedSpaceHome];
  105. if(empty($method)) return $this->locate($this->createLink('doc', 'mySpace'));
  106. if(!is_numeric($lastViewedSpace) || !is_numeric($lastViewedLib)) return $this->locate($this->createLink('doc', 'mySpace'));
  107. return $this->locate($this->createLink('doc', $method, "objectID={$lastViewedSpace}&libID={$lastViewedLib}"));
  108. }
  109. /**
  110. * 设置上次访问的文档对象。
  111. * Set last viewed doc object.
  112. *
  113. * @access public
  114. * @return void
  115. */
  116. public function ajaxSetLastViewed()
  117. {
  118. if(empty($_POST)) return $this->send(array('result' => 'fail'));
  119. $this->doc->setLastViewed($_POST);
  120. return $this->send(array('result' => 'success'));
  121. }
  122. /**
  123. * 文档仪表盘。
  124. * Document dashboard.
  125. *
  126. * @access public
  127. * @return void
  128. */
  129. public function index()
  130. {
  131. $this->session->set('docList', $this->app->getURI(true), 'doc');
  132. echo $this->fetch('block', 'dashboard', 'dashboard=doc');
  133. }
  134. /**
  135. * 禅道数据列表。
  136. * Zentao data list.
  137. *
  138. * @param string $type
  139. * @param int|string $blockID
  140. * @access public
  141. * @return void
  142. */
  143. public function zentaoList($type, $blockID)
  144. {
  145. if(is_string($blockID)) $blockID = (int)str_replace('__TML_ZENTAOLIST__', '', $blockID);
  146. $blockData = $this->doc->getZentaoList($blockID);
  147. if(!$blockData)
  148. {
  149. if(helper::isAjaxRequest('fetch'))
  150. {
  151. echo '<div class="text-gray text-sm surface p-1">' . $this->lang->notFound . '</div>';
  152. return;
  153. }
  154. return $this->sendError($this->lang->notFound);
  155. }
  156. $doc = $this->doc->getByID($blockData->doc);
  157. $this->view->isTemplate = !empty($doc->templateType) && !in_array($blockData->extra, array('fromReview', 'fromReport'));
  158. $this->view->fromReport = $blockData->extra == 'fromReport';
  159. $noSupport = false;
  160. if($this->view->fromReport)
  161. {
  162. $project = $this->loadModel('project')->fetchByID((int)$doc->project);
  163. $noSupport = in_array($type, array('HLDS', 'DDS', 'DBDS', 'ADS')) && in_array($project->model, array('scrum', 'agileplus', 'kanban'));
  164. }
  165. $this->view->noSupport = $noSupport;
  166. if($this->view->isTemplate)
  167. {
  168. $this->view->title = sprintf($this->lang->doc->insertTitle, $this->lang->docTemplate->zentaoList[$type]);
  169. $this->view->type = $type;
  170. $this->view->blockID = $blockID;
  171. $this->view->settings = $blockData->settings;
  172. $this->view->searchTab = zget($blockData->content, 'searchTab', '');
  173. if($type == 'productCase' || $type == 'projectCase') $this->view->caseStage = $blockData->content->caseStage;
  174. return $this->display();
  175. }
  176. $fromTemplate = in_array($blockData->extra, array('fromTemplate', 'fromReview', 'fromReport'));
  177. if($fromTemplate)
  178. {
  179. $this->view->title = sprintf($this->lang->doc->insertTitle, $this->lang->docTemplate->zentaoList[$type]);
  180. $this->view->searchTab = zget($blockData->content, 'searchTab', '');
  181. $this->view->isSetted = isset($blockData->content->data) && isset($blockData->content->cols) || isset($blockData->content->ganttOptions);
  182. if($type == 'productCase' || $type == 'projectCase') $this->view->caseStage = $blockData->content->caseStage;
  183. }
  184. else
  185. {
  186. $this->view->title = sprintf($this->lang->doc->insertTitle, $this->lang->doc->zentaoList[$type]);
  187. }
  188. if($type == 'gantt')
  189. {
  190. $this->view->ganttData = (array)zget($blockData->content, 'ganttOptions', array());
  191. $this->view->ganttFields = (array)zget($blockData->content, 'ganttFields', array());
  192. $this->view->showFields = zget($blockData->content, 'showFields', '');
  193. }
  194. else
  195. {
  196. $data = (array)zget($blockData->content, 'data', array());
  197. if($type == 'task')
  198. {
  199. foreach($data as $task) $task->canView = $this->execution->checkPriv($task->execution);
  200. }
  201. $this->app->loadClass('pager', true);
  202. $this->view->idList = (array)zget($blockData->content, 'idList', array());
  203. $this->view->cols = (array)zget($blockData->content, 'cols', array());
  204. $this->view->data = $data;
  205. $this->view->pager = new pager(count($data), 10);
  206. }
  207. $this->view->type = $type;
  208. $this->view->settings = $blockData->settings;
  209. $this->view->users = $this->loadModel('user')->getPairs('noletter|pofirst');
  210. $this->view->blockID = $blockID;
  211. $this->view->fromTemplate = $fromTemplate;
  212. if(strpos(',productStory,ER,UR,planStory,projectStory', $type) !== false) $this->docZen->assignStoryGradeData($type);
  213. if($type == 'productRelease')
  214. {
  215. $releaseList = array();
  216. foreach($this->view->data as $release)
  217. {
  218. if($release->id == $release->rowID) $releaseList[$release->id] = $release;
  219. }
  220. $children = implode(',', array_column($releaseList, 'releases'));
  221. $childReleases = $this->loadModel('release')->getListByCondition(explode(',', $children), 0, true);
  222. $this->view->data = $this->release->processReleaseListData($releaseList, $childReleases, false);
  223. }
  224. $this->display();
  225. }
  226. /**
  227. * 导出禅道数据列表。
  228. * Export Zentao data list.
  229. *
  230. * @param int|string $blockID
  231. * @access public
  232. * @return void
  233. */
  234. public function ajaxExportZentaoList($blockID)
  235. {
  236. if(is_string($blockID)) $blockID = (int)str_replace('__TML_ZENTAOLIST__', '', $blockID);
  237. $blockData = $this->doc->getZentaoList($blockID);
  238. if(!$blockData) return $this->lang->notFound;
  239. if(!helper::isAjaxRequest('fetch')) return $this->locate(inlink('zentaoList', "type={$blockData->type}&blockID={$blockID}"));
  240. if(empty($blockData->title))
  241. {
  242. $blockType = $blockData->type;
  243. $blockContent = $blockData->content;
  244. $templateLang = zget($this->lang, 'docTemplate', array());
  245. $searchTab = zget($blockContent, 'searchTab', '');
  246. $blockTitle = '';
  247. if(!empty($templateLang))
  248. {
  249. $blockTitle = empty($templateLang->searchTabList[$blockType][$searchTab]) ? '' : $templateLang->searchTabList[$blockType][$searchTab] . $templateLang->of;
  250. if($blockType == 'bug' && $searchTab == 'overduebugs') $blockTitle = $templateLang->overdue . $templateLang->of;
  251. if(!empty($blockContent->caseStage)) $blockTitle .= $this->app->loadLang('testcase')->testcase->stageList[$blockContent->caseStage];
  252. }
  253. $blockData->title = $blockTitle . zget($this->lang->doc->zentaoList, $blockType, '') . $this->lang->doc->list;
  254. }
  255. $content = $this->docZen->exportZentaoList($blockData);
  256. echo $content;
  257. }
  258. /**
  259. * 构建禅道数据列表。
  260. * Build Zentao data list.
  261. *
  262. * @param int $docID
  263. * @param string $type
  264. * @param int $oldBlockID
  265. * @access public
  266. * @return void
  267. */
  268. public function buildZentaoList($docID, $type, $oldBlockID = 0)
  269. {
  270. $docblock = new stdClass();
  271. $docblock->doc = $docID;
  272. $docblock->type = $type;
  273. $docblock->settings = $this->post->url;
  274. if($type == 'gantt')
  275. {
  276. $docblock->content = json_encode(array('ganttOptions' => json_decode($this->post->ganttOptions), 'showFields' => $this->post->showFields, 'ganttFields' => json_decode($this->post->ganttFields)));
  277. }
  278. else
  279. {
  280. $docblock->content = json_encode(array('cols' => json_decode($this->post->cols), 'data' => json_decode($this->post->data), 'idList' => $this->post->idList));
  281. }
  282. $this->dao->insert(TABLE_DOCBLOCK)->data($docblock)->exec();
  283. if(dao::isError()) return print(json_encode(array('result' => 'fail', 'message' => dao::getError())));
  284. $newBlockID = $this->dao->lastInsertId();
  285. return print(json_encode(array('result' => 'success', 'oldBlockID' => $oldBlockID, 'newBlockID' => $newBlockID)));
  286. }
  287. /**
  288. * 我的空间。
  289. * My space.
  290. *
  291. * @param int $objectID
  292. * @param int $libID
  293. * @param int $moduleID
  294. * @param string $browseType all|draft|bysearch
  295. * @param int $param
  296. * @param string $orderBy
  297. * @param int $recTotal
  298. * @param int $recPerPage
  299. * @param int $pageID
  300. * @access public
  301. * @return void
  302. * @param string $mode
  303. * @param int $docID
  304. * @param string $search
  305. */
  306. public function mySpace($objectID = 0, $libID = 0, $moduleID = 0, $browseType = 'all', $param = 0, $orderBy = 'order_asc', $recTotal = 0, $recPerPage = 20, $pageID = 1, $mode = '', $docID = 0, $search = '')
  307. {
  308. $this->docZen->initLibForMySpace();
  309. echo $this->fetch('doc', 'app', "type=mine&spaceID=$objectID&libID=$libID&moduleID=$moduleID&docID=$docID&mode=$mode&orderBy=$orderBy&recTotal=$recTotal&recPerPage=$recPerPage&pageID=$pageID&filterType=$browseType&search=$search");
  310. }
  311. /**
  312. * 创建一个空间。
  313. * Create a space.
  314. *
  315. * @param string $type
  316. * @access public
  317. * @return void
  318. */
  319. public function createSpace($type = '')
  320. {
  321. if(!empty($_POST))
  322. {
  323. $this->lang->doc->name = $this->lang->doclib->spaceName;
  324. $space = form::data()->setDefault('addedBy', $this->app->user->account)->get();
  325. if($type) $space->type = $type;
  326. $spaceID = $this->doc->doInsertLib($space);
  327. if(dao::isError()) return $this->send(array('result' => 'fail', 'message' => dao::getError()));
  328. $this->loadModel('action')->create('docspace', $spaceID, 'created');
  329. return $this->send(array('result' => 'success', 'message' => $this->lang->saveSuccess, 'closeModal' => true, 'load' => $this->createLink('doc', 'teamSpace', "objectID={$spaceID}"), 'docApp' => array('call' => 'selectSpace', 'args' => array($spaceID, true))));
  330. }
  331. $this->display();
  332. }
  333. /**
  334. * 创建一个文档库。
  335. * Create a library.
  336. *
  337. * @param string $type api|project|product|execution|custom|mine
  338. * @param int $objectID
  339. * @param int $libID
  340. * @access public
  341. * @return void
  342. */
  343. public function createLib($type = '', $objectID = 0, $libID = 0)
  344. {
  345. $this->app->loadLang('api');
  346. /* 项目模板下setMenu会修改common语言项,所以执行文档要先执行setAclForCreateLib。 */
  347. if($type != 'project') $this->docZen->setAclForCreateLib($type);
  348. $this->doc->setMenuByType($type, (int)$objectID, (int)$libID);
  349. if($type == 'project') $this->docZen->setAclForCreateLib($type);
  350. if(!empty($_POST))
  351. {
  352. $lib = $this->docZen->buildLibForCreateLib();
  353. if(dao::isError()) return $this->send(array('result' => 'fail', 'message' => dao::getError()));
  354. $libID = $this->doc->createLib($lib, (string)$this->post->type, (string)$this->post->libType);
  355. if(dao::isError()) return $this->send(array('result' => 'fail', 'message' => dao::getError()));
  356. if($type == 'custom' || $type == 'mine')
  357. {
  358. $lib = $this->doc->getLibByID($libID);
  359. $objectID = $lib->parent;
  360. }
  361. return $this->docZen->responseAfterCreateLib($type, $objectID, $libID, $lib->name, $lib->orderBy);
  362. }
  363. $objects = array();
  364. if($type == 'project')
  365. {
  366. $this->view->project = $this->project->getById($objectID);
  367. if($this->app->tab == 'doc') $this->view->executionPairs = $this->execution->getPairs($objectID, 'all', 'multiple,leaf,noprefix');
  368. }
  369. if($type == 'execution')
  370. {
  371. $objects = $this->execution->getPairs(0, 'all', 'multiple,leaf,noprefix,withobject');
  372. $execution = $this->execution->getByID($objectID);
  373. if($execution->type == 'stage') $this->lang->doc->execution = str_replace($this->lang->executionCommon, $this->lang->project->stage, $this->lang->doc->execution);
  374. $this->view->execution = $this->doc->fetchByID($objectID, 'execution');
  375. }
  376. if($type == 'custom' || $type == 'mine' || $type == 'doctemplate')
  377. {
  378. $lib = $this->doc->getLibByID($libID);
  379. $this->view->spaces = $this->doc->getSubSpacesByType($type);
  380. $this->view->spaceID = !empty($lib->parent) ? $lib->parent : $objectID;
  381. }
  382. $this->view->groups = $this->loadModel('group')->getPairs();
  383. $this->view->users = $this->user->getPairs('nocode|noclosed');
  384. $this->view->objects = $objects;
  385. $this->view->type = $type;
  386. $this->view->objectID = $objectID;
  387. $this->display();
  388. }
  389. /**
  390. * 编辑一个文档空间。
  391. * Edit a doc space.
  392. *
  393. * @param int $spaceID
  394. * @access public
  395. * @return void
  396. */
  397. public function editSpace($spaceID)
  398. {
  399. $this->commonEditAction($spaceID);
  400. $this->display();
  401. }
  402. /**
  403. * 编辑一个文档库。
  404. * Edit a library.
  405. *
  406. * @param int $libID
  407. * @access public
  408. * @return void
  409. */
  410. public function editLib($libID)
  411. {
  412. $this->commonEditAction($libID);
  413. $this->display();
  414. }
  415. /**
  416. * 编辑空间和编辑库的公用方法。
  417. * Edit a lib or space.
  418. *
  419. * @param int $libID
  420. * @access public
  421. * @return void
  422. */
  423. public function commonEditAction($libID)
  424. {
  425. if(!common::hasPriv('doc', 'editSpace') && !common::hasPriv('doc', 'editLib')) return;
  426. $lib = $this->doc->getLibByID($libID);
  427. /* 项目模板下setMenu会修改common语言项,所以执行文档要先执行setAclForCreateLib。 */
  428. if($lib->type != 'project') $this->docZen->setAclForEditLib($lib);
  429. $this->doc->setMenuByType($lib->type, (int)zget($lib, $lib->type, 0), (int)$libID);
  430. if($lib->type == 'project') $this->docZen->setAclForEditLib($lib);
  431. if(!empty($_POST))
  432. {
  433. $this->lang->doc->name = $this->lang->nameAB;
  434. $libData = form::data($this->config->doc->form->editlib)->get();
  435. if(dao::isError()) return $this->send(array('result' => 'fail', 'message' => dao::getError()));
  436. $changes = $this->doc->updateLib($libID, $libData);
  437. if(dao::isError()) $this->send(array('result' => 'fail', 'message' => dao::getError()));
  438. if($changes)
  439. {
  440. $object = ($lib->type == 'custom' && $lib->parent == 0) ? 'docspace' : 'doclib';
  441. $actionID = $this->action->create($object, $libID, 'edited');
  442. $this->action->logHistory($actionID, $changes);
  443. }
  444. $lib = $this->doc->getLibByID($libID);
  445. $docAppActions = array();
  446. $docAppActions[] = array('update', ($lib->parent == 0) ? 'space' : 'lib', $lib);
  447. $docAppActions[] = array('home:loadHomeLibs');
  448. $docAppActions[] = array('list:load');
  449. return $this->send(array('message' => $this->lang->saveSuccess, 'result' => 'success', 'closeModal' => true, 'docApp' => $docAppActions));
  450. }
  451. if(!empty($lib->product)) $this->view->object = $this->product->getByID($lib->product);
  452. if(!empty($lib->project) && empty($lib->execution)) $this->view->object = $this->project->getByID($lib->project);
  453. if(!empty($lib->execution))
  454. {
  455. $execution = $this->execution->getByID($lib->execution);
  456. if($execution->type == 'stage')
  457. {
  458. if($execution->grade > 1)
  459. {
  460. $parentExecutions = $this->execution->getPairsByList(explode(',', trim($execution->path, ',')), 'stage,kanban,sprint');
  461. $execution->name = implode('/', $parentExecutions);
  462. }
  463. $this->lang->doc->execution = str_replace($this->lang->executionCommon, $this->lang->project->stage, $this->lang->doc->execution);
  464. }
  465. $this->view->object = $execution;
  466. }
  467. $this->view->lib = $lib;
  468. $this->view->groups = $this->loadModel('group')->getPairs();
  469. $this->view->users = $this->user->getPairs('noletter|noclosed', $lib->users);
  470. $this->view->libID = $libID;
  471. }
  472. /**
  473. * 删除一个文档空间。
  474. * Delete a doc space.
  475. *
  476. * @param int $libID
  477. * @access public
  478. * @return void
  479. */
  480. public function deleteSpace($libID)
  481. {
  482. $this->commonDeleteAction($libID);
  483. }
  484. /**
  485. * 删除一个文档库。
  486. * Delete a library.
  487. *
  488. * @param int $libID
  489. * @access public
  490. * @return void
  491. */
  492. public function deleteLib($libID)
  493. {
  494. $this->commonDeleteAction($libID);
  495. }
  496. /**
  497. * 删除空间和删除库的公用方法。
  498. * Delete a lib or space.
  499. *
  500. * @param int $libID
  501. * @access public
  502. * @return void
  503. */
  504. public function commonDeleteAction($libID)
  505. {
  506. if(in_array($libID, array('product', 'execution'))) return;
  507. $lib = $this->doc->getLibByID($libID);
  508. if(!empty($lib->main)) return $this->send(array('result' => 'fail', 'message' => $this->lang->doc->errorMainSysLib, 'load' => array('alert' => $this->lang->doc->errorMainSysLib)));
  509. $this->dao->update(TABLE_DOCLIB)->set('deleted')->eq('1')->where('id')->eq($libID)->exec();
  510. $object = ($lib->type == 'custom' && $lib->parent == 0) ? 'docspace' : 'doclib';
  511. $this->loadModel('action')->create($object, $libID, 'deleted', '', ACTIONMODEL::CAN_UNDELETED);
  512. $moduleName = 'doc';
  513. $objectType = $lib->type;
  514. $methodName = zget($this->config->doc->spaceMethod, $objectType);
  515. if($this->app->tab == 'doc') return $this->send(array('result' => 'success', 'load' => $this->createLink($moduleName, $methodName), 'app' => $this->app->tab));
  516. $objectID = strpos(',product,project,execution,', ",$objectType,") !== false ? $lib->{$objectType} : 0;
  517. if($this->app->tab == 'execution' && $objectType == 'execution')
  518. {
  519. $moduleName = 'execution';
  520. $methodName = 'doc';
  521. }
  522. $browseLink = $this->createLink($moduleName, $methodName, "objectID=$objectID");
  523. return $this->send(array('result' => 'success', 'load' => $browseLink, 'app' => $this->app->tab));
  524. }
  525. /**
  526. * 文档模板列表。
  527. * Browse template list.
  528. *
  529. * @param int $libID
  530. * @param string $type
  531. * @param mixed $docID
  532. * @param string $orderBy
  533. * @param int $recPerPage
  534. * @param int $pageID
  535. * @access public
  536. * @return void
  537. * @param string $mode
  538. */
  539. public function browseTemplate($libID = 0, $type = 'all', $docID = 0, $orderBy = 'id_desc', $recPerPage = 20, $pageID = 1, $mode = 'home')
  540. {
  541. /* 添加内置的范围、分类、文档模板。*/
  542. /* Add the built-in scopes and type and doc template. */
  543. $builtInScopes = $this->dao->select('id')->from(TABLE_DOCLIB)->where('type')->eq('template')->andWhere('main')->eq('1')->fetchAll();
  544. if(empty($builtInScopes))
  545. {
  546. $this->doc->addBuiltInScopes();
  547. $this->doc->addBuiltInDocTemplateType();
  548. $this->doc->addBuiltInDocTemplateByType();
  549. }
  550. $this->lang->doc->menu->template['alias'] .= ',' . $this->app->rawMethod;
  551. $libModules = $this->doc->getTemplateModules($libID);
  552. if($mode == 'create' && empty($libModules)) return $this->send(array('result' => 'success', 'load' => array('alert' => $this->lang->docTemplate->createTypeFirst)));
  553. $templateList = $this->doc->getDocTemplateList(0, $type, $orderBy);
  554. $templateList = $this->doc->filterDeletedDocs($templateList);
  555. $templateList = $this->doc->filterPrivDocs($templateList, 'template');
  556. $allModules = $this->doc->getTemplateModules();
  557. $allModules = array_column($allModules, 'fullName', 'id');
  558. foreach($templateList as $template) $template->moduleName = zget($allModules, $template->module);
  559. $docVersion = 0;
  560. if(is_string($docID) && strpos($docID, '_') !== false) list($docID, $docVersion) = explode('_', $docID);
  561. $this->view->title = $this->lang->doc->template;
  562. $this->view->libID = $libID;
  563. $this->view->users = $this->loadModel('user')->getPairs('noclosed,noletter');
  564. $this->view->templateList = $templateList;
  565. $this->view->docID = $docID;
  566. $this->view->docVersion = $docVersion;
  567. $this->view->orderBy = $orderBy;
  568. $this->view->recPerPage = $recPerPage;
  569. $this->view->pageID = $pageID;
  570. $this->view->mode = $mode;
  571. $this->view->hasModules = count($libModules) ? true : false;
  572. $this->view->scopes = $this->doc->getTemplateScopes();
  573. $this->display();
  574. }
  575. /**
  576. * 创建一个模板类型。
  577. * Add a template type.
  578. *
  579. * @param int $scope
  580. * @param int|string $parentModule
  581. * @access public
  582. * @return void
  583. */
  584. public function addTemplateType($scope, $parentModule = '')
  585. {
  586. $moduleList = $this->doc->getTemplateModules($scope, '1');
  587. if(!empty($_POST))
  588. {
  589. $this->lang->doc->name = $this->lang->docTemplate->typeName;
  590. $moduleData = form::data($this->config->doc->form->addTemplateType)
  591. ->setDefault('type', 'docTemplate')
  592. ->setDefault('path', '')
  593. ->get();
  594. $moduleData->grade = $moduleData->parent === 0 ? 1 : 2;
  595. if(dao::isError()) return $this->send(array('result' => 'fail', 'message' => dao::getError()));
  596. $this->doc->addTemplateType($moduleData);
  597. if(dao::isError()) return $this->send(array('result' => 'fail', 'message' => dao::getError()));
  598. return $this->docZen->responseAfterAddTemplateType($scope);
  599. }
  600. $moduleItems = array();
  601. if($parentModule === 0)
  602. {
  603. $moduleItems[] = array('value' => 0, 'text' => '/');
  604. }
  605. else
  606. {
  607. foreach($moduleList as $module) $moduleItems[] = array('value' => $module->id, 'text' => '/' . $module->name);
  608. $moduleItems[] = array('value' => 0, 'text' => '/');
  609. }
  610. $scopeList = $this->doc->getTemplateScopes();
  611. $this->view->scope = $scope;
  612. $this->view->scopes = $this->doc->getScopeItems($scopeList);
  613. $this->view->moduleItems = $moduleItems;
  614. $this->view->parentModule = $parentModule === '' ? current($moduleItems) : $parentModule;
  615. $this->display();
  616. }
  617. /**
  618. * 删除一个模板类型。
  619. * Delete a template type.
  620. *
  621. * @param int $moduleID
  622. * @access public
  623. * @return void
  624. */
  625. public function deleteTemplateType($moduleID)
  626. {
  627. $templates = $this->doc->getTemplatesByType($moduleID);
  628. if(empty($templates))
  629. {
  630. $this->dao->update(TABLE_MODULE)->set('deleted')->eq('1')->where('id')->eq($moduleID)->andWhere('type')->eq('docTemplate')->exec();
  631. $this->dao->update(TABLE_MODULE)->set('deleted')->eq('1')->where('parent')->eq($moduleID)->andWhere('type')->eq('docTemplate')->exec();
  632. return $this->sendSuccess(array('load' => true));
  633. }
  634. else
  635. {
  636. return $this->send(array('result' => 'fail', 'message' => $this->lang->docTemplate->errorDeleteType));
  637. }
  638. }
  639. /**
  640. * 编辑一个模板类型。
  641. * Edit a template type.
  642. *
  643. * @param int $moduleID
  644. * @access public
  645. * @return void
  646. */
  647. public function editTemplateType($moduleID)
  648. {
  649. echo $this->fetch('tree', 'edit', "moduleID={$moduleID}&type=docTemplate");
  650. }
  651. /**
  652. * 创建一个文档模板。
  653. * Create a doc template.
  654. *
  655. * @param int $moduleID
  656. * @access public
  657. * @return void
  658. */
  659. public function createTemplate($moduleID = 0)
  660. {
  661. if(!empty($_POST))
  662. {
  663. $this->lang->doc->title = $_POST['type'] == 'chapter' ? $this->lang->doc->chapterName : $this->lang->docTemplate->title;
  664. helper::setcookie('lastDocModule', $moduleID);
  665. $docData = form::data()
  666. ->setDefault('addedBy', $this->app->user->account)
  667. ->setDefault('editedBy', $this->app->user->account)
  668. ->get();
  669. if(empty($docData->module)) return $this->sendError(sprintf($this->lang->error->notempty, $this->lang->docTemplate->module));
  670. if(!empty($docData->parent))
  671. {
  672. $parentTemplate = $this->doc->fetchByID((int)$docData->parent);
  673. $docData->module = $parentTemplate->module;
  674. $docData->lib = (int)$parentTemplate->lib;
  675. $docData->acl = $parentTemplate->acl;
  676. $docData->templateType = $parentTemplate->templateType;
  677. }
  678. $docResult = $this->doc->create($docData);
  679. if(!$docResult || dao::isError()) return $this->send(array('result' => 'fail', 'message' => dao::getError()));
  680. return $this->docZen->responseAfterCreate($docResult, 'docTemplate');
  681. }
  682. }
  683. /**
  684. * 编辑一个文档。
  685. * Edit a doc.
  686. *
  687. * @param int $docID
  688. * @access public
  689. * @return void
  690. */
  691. public function editTemplate($docID)
  692. {
  693. $doc = $this->doc->getByID($docID);
  694. if(!empty($_POST))
  695. {
  696. $this->lang->doc->module = $this->lang->docTemplate->module;
  697. $changes = $files = array();
  698. $docData = form::data()
  699. ->setDefault('editedBy', $this->app->user->account)
  700. ->setIF(!isset($_POST['parent']), 'parent', $doc->parent)
  701. ->setIF(strpos(",$doc->editedList,", ",{$this->app->user->account},") === false, 'editedList', $doc->editedList . ",{$this->app->user->account}")
  702. ->setIF($this->post->type == 'chapter', 'content', $doc->content)
  703. ->setIF($this->post->type == 'chapter', 'rawContent', $doc->rawContent)
  704. ->remove('fromVersion')
  705. ->get();
  706. $result = $this->doc->update($docID, $docData);
  707. if(dao::isError())
  708. {
  709. if(!empty(dao::$errors['lib']) || !empty(dao::$errors['keywords'])) return $this->send(array('result' => 'fail', 'message' => dao::getError(), 'callback' => "zui.Modal.open({id: 'modalBasicInfo'});"));
  710. return $this->send(array('result' => 'fail', 'message' => dao::getError()));
  711. }
  712. $changes = $result['changes'];
  713. $files = $result['files'];
  714. return $this->docZen->responseAfterEditTemplate($doc, $changes, $files);
  715. }
  716. }
  717. /**
  718. * 上传文档。
  719. * Upload docs.
  720. *
  721. * @param int $docID
  722. * @param string $objectType product|project|execution|custom
  723. * @param int $objectID
  724. * @param int $libID
  725. * @param int $moduleID
  726. * @param string $docType html|word|ppt|excel|attachment
  727. * @access public
  728. * @return void
  729. */
  730. public function uploadDocs($docID, $objectType, $objectID, $libID, $moduleID = 0, $docType = '')
  731. {
  732. if(!empty($_POST))
  733. {
  734. /* parent带‘m_’前缀为目录。*/
  735. if(isset($_POST['parent']) && strpos($_POST['parent'], 'm_') !== false)
  736. {
  737. $_POST['module'] = str_replace('m_', '', $_POST['parent']);
  738. $_POST['parent'] = 0;
  739. }
  740. $libID = (int)$this->post->lib;
  741. if(!$libID) return $this->send(array('result' => 'fail', 'message' => array('lib' => sprintf($this->lang->error->notempty, $this->lang->doc->lib))));
  742. $doclib = $this->loadModel('doc')->getLibByID($libID);
  743. $canVisit = $this->docZen->checkPrivForCreate($doclib, $objectType);
  744. if(!$canVisit) return $this->send(array('result' => 'fail', 'message' => $this->lang->doc->accessDenied));
  745. $moduleID = $this->post->module;
  746. helper::setcookie('lastDocModule', $moduleID);
  747. if(!isset($_POST['lib']) && strpos($_POST['module'], '_') !== false) list($_POST['lib'], $_POST['module']) = explode('_', $_POST['module']);
  748. if($_POST['type'] == 'attachment' && empty($_FILES['files']['name'][0]))
  749. {
  750. $this->config->doc->form->create['title']['required'] = false;
  751. $this->config->doc->form->create['title']['skipRequired'] = true;
  752. }
  753. $this->config->doc->create->requiredFields = trim(str_replace(array(',content,', ',keywords,'), ",", ",{$this->config->doc->create->requiredFields},"), ',');
  754. $docData = form::data(!empty($docID) ? $this->config->doc->form->edit : $this->config->doc->form->create)->remove('fromVersion')->get();
  755. if(empty($docID)) $docData->addedBy = $this->app->user->account;
  756. if(!empty($docID)) $docData->editedBy = $this->app->user->account;
  757. if(!empty($docID))
  758. {
  759. $docResult = $this->doc->update($docID, $docData);
  760. $docData->id = $docID;
  761. }
  762. elseif($this->post->uploadFormat == 'combinedDocs')
  763. {
  764. $docResult = $this->doc->create($docData);
  765. }
  766. else
  767. {
  768. $docResult = $this->doc->createSeperateDocs($docData);
  769. }
  770. if(dao::isError()) return $this->send(array('result' => 'fail', 'message' => dao::getError()));
  771. return !empty($docID) ? $this->send($this->docZen->responseAfterEdit($docData, $docResult['changes'], $docResult['files'], $docResult['deletedFiles'])) : $this->docZen->responseAfterUploadDocs($docResult);
  772. }
  773. if($objectType == 'execution' && $libID) // 此时传入的objectID是projectID,用lib的信息更改回executionID
  774. {
  775. $lib = $this->doc->getLibByID($libID);
  776. $objectID = $this->doc->getObjectIDByLib($lib);
  777. }
  778. $this->docZen->assignVarsForUploadDocs($docID, $objectType, $objectID, $libID, $moduleID, $docType);
  779. $this->display();
  780. }
  781. /**
  782. * 创建一个文档。
  783. * Create a doc.
  784. *
  785. * @param string $objectType product|project|execution|custom
  786. * @param int $objectID
  787. * @param int $libID
  788. * @param int $moduleID
  789. * @param string $docType html|word|ppt|excel
  790. * @param int $appendLib
  791. * @access public
  792. * @return void
  793. */
  794. public function create($objectType, $objectID, $libID, $moduleID = 0, $docType = '', $appendLib = 0)
  795. {
  796. if(!empty($_POST))
  797. {
  798. /* parent带‘m_’前缀为目录。*/
  799. if(isset($_POST['parent']) && strpos($_POST['parent'], 'm_') !== false)
  800. {
  801. $_POST['module'] = str_replace('m_', '', $_POST['parent']);
  802. $_POST['parent'] = 0;
  803. }
  804. $libID = (int)$this->post->lib;
  805. $docLib = $this->loadModel('doc')->getLibByID($libID);
  806. if($docLib)
  807. {
  808. $canVisit = $this->docZen->checkPrivForCreate($docLib, $objectType);
  809. if(!$canVisit) return $this->send(array('result' => 'fail', 'message' => $this->lang->doc->accessDenied));
  810. }
  811. $moduleID = $this->post->module;
  812. helper::setcookie('lastDocModule', $moduleID);
  813. if(!isset($_POST['lib']) && strpos($_POST['module'], '_') !== false) list($_POST['lib'], $_POST['module']) = explode('_', $_POST['module']);
  814. if($_POST['type'] == 'chapter') $this->lang->doc->title = $this->lang->doc->chapterName;
  815. $docData = form::data()
  816. ->setDefault('addedBy', $this->app->user->account)
  817. ->setDefault('editedBy', $this->app->user->account)
  818. ->get();
  819. if($docData->parent && !$docData->module)
  820. {
  821. $parentDoc = $this->doc->getByID($docData->parent);
  822. $docData->module = $parentDoc->module;
  823. }
  824. $docResult = $this->doc->create($docData);
  825. if(!$docResult || dao::isError()) return $this->send(array('result' => 'fail', 'message' => dao::getError()));
  826. return $this->docZen->responseAfterCreate($docResult);
  827. }
  828. $this->docZen->assignVarsForCreate($objectType, $objectID, $libID, $moduleID, $docType);
  829. $lib = $this->view->lib;
  830. if(empty($lib)) return $this->send(array('result' => 'fail', 'message' => $this->lang->doc->errorEmptySpaceLib));
  831. $objectID = $this->view->objectID;
  832. $libData = $this->doc->setMenuByType($lib->type, (int)$objectID, (int)$lib->id, (int)$appendLib);
  833. if(is_string($libData)) return $this->locate($libData);
  834. list($libs, $libID, $object, $objectID, $objectDropdown) = $libData;
  835. if($this->config->edition != 'open') $this->loadModel('file');
  836. if($lib->type == 'custom' || $lib->type == 'mine') $this->view->spaces = $this->docZen->getAllSpaces($lib->type == 'mine' ? 'onlymine' : 'nomine');
  837. $this->view->title = zget($lib, 'name', '', $lib->name . $this->lang->hyphen) . $this->lang->doc->create;
  838. $this->view->object = $object;
  839. $this->view->objectDropdown = $objectDropdown;
  840. $this->view->libTree = $this->doc->getLibTree((int)$libID, $libs, $objectType, (int)$moduleID, (int)$objectID);
  841. $this->view->linkParams = "objectID={$objectID}&%s&browseType=&orderBy=status,id_desc&param=0";
  842. if(!empty($objectType) && $objectType !== 'custom')
  843. {
  844. $objectIDVar = $objectType . 'ID';
  845. $this->view->$objectIDVar = $objectID;
  846. }
  847. $this->display();
  848. }
  849. /**
  850. * 编辑一个文档。
  851. * Edit a doc.
  852. *
  853. * @param int $docID
  854. * @param bool $comment
  855. * @param int $appendLib
  856. * @access public
  857. * @return void
  858. */
  859. public function edit($docID, $comment = false, $appendLib = 0)
  860. {
  861. $doc = $this->doc->getByID($docID);
  862. if(!empty($_POST))
  863. {
  864. /* parent带‘m_’前缀为目录。*/
  865. if(isset($_POST['parent']) && strpos($_POST['parent'], 'm_') !== false)
  866. {
  867. $_POST['module'] = str_replace('m_', '', $_POST['parent']);
  868. $_POST['parent'] = 0;
  869. }
  870. if(!$doc) return $this->send(array('result' => 'fail', 'message' => $this->lang->doc->errorNotFound));
  871. $isOpen = $doc->acl == 'open';
  872. $currentAccount = $this->app->user->account;
  873. $isAuthorOrAdmin = $doc->acl == 'private' && ($doc->addedBy == $currentAccount || $this->app->user->admin);
  874. $isInEditUsers = strpos(",$doc->users,", ",$currentAccount,") !== false;
  875. $isInEditGroups = false;
  876. if(!empty($doc->groups))
  877. {
  878. foreach($this->app->user->groups as $groupID)
  879. {
  880. if(strpos(",$doc->groups,", ",$groupID,") !== false) $isInEditGroups = true;
  881. }
  882. }
  883. if(!$isOpen && !$isAuthorOrAdmin && !$isInEditUsers && !$isInEditGroups) return $this->send(array('result' => 'fail', 'message' => $this->lang->doc->needEditable));
  884. if($doc->type == 'chapter') $this->lang->doc->title = $this->lang->doc->chapterName;
  885. $changes = $files = array();
  886. if($comment == false)
  887. {
  888. $docData = form::data()
  889. ->setDefault('editedBy', $this->app->user->account)
  890. ->setDefault('acl', $doc->acl)
  891. ->setIF(strpos(",$doc->editedList,", ",{$this->app->user->account},") === false, 'editedList', $doc->editedList . ",{$this->app->user->account}")
  892. ->setIF(!isset($_POST['module']), 'module', $doc->module)
  893. ->setIF(!isset($_POST['mailto']), 'mailto', $doc->mailto)
  894. ->setIF(!isset($_POST['users']), 'users', $doc->users)
  895. ->setIF(!isset($_POST['groups']), 'groups', $doc->groups)
  896. ->setIF(!isset($_POST['readUsers']), 'readUsers', $doc->readUsers)
  897. ->setIF(!isset($_POST['readGroups']), 'readGroups', $doc->readGroups)
  898. ->setIF(!isset($_POST['fromVersion']), 'fromVersion', $doc->fromVersion)
  899. ->removeIF($this->post->project === false, 'project')
  900. ->removeIF($this->post->product === false, 'product')
  901. ->removeIF($this->post->execution === false, 'execution')
  902. ->get();
  903. $result = $this->doc->update($docID, $docData);
  904. if(dao::isError())
  905. {
  906. if(!empty(dao::$errors['lib']) || !empty(dao::$errors['keywords'])) return $this->send(array('result' => 'fail', 'message' => dao::getError(), 'callback' => "zui.Modal.open({id: 'modalBasicInfo'});"));
  907. return $this->send(array('result' => 'fail', 'message' => dao::getError()));
  908. }
  909. $changes = $result['changes'];
  910. $files = $result['files'];
  911. }
  912. return $this->send($this->docZen->responseAfterEdit($doc, $changes, $files));
  913. }
  914. /* Get doc and set menu. */
  915. $moduleID = (int)$doc->module;
  916. $libID = (int)$doc->lib;
  917. $lib = $this->doc->getLibByID($libID);
  918. $objectType = isset($lib->type) ? $lib->type : 'custom';
  919. $objectID = zget($lib, $lib->type, 0);
  920. if($lib->type == 'custom') $objectID = $lib->parent;
  921. if($doc->type == 'text' || $doc->type == 'article')
  922. {
  923. echo $this->fetch('doc', 'app', "type=$objectType&spaceID=$objectID&libID=$libID&moduleID=$doc->module&docID=$docID&mode=edit");
  924. return;
  925. }
  926. $libPairs = $this->doc->getLibs($lib->type, '', $doc->lib, $objectID);
  927. list($libs, $libID, $object, $objectID, $objectDropdown) = $this->doc->setMenuByType($objectType, $objectID, (int)$doc->lib, (int)$appendLib);
  928. if($lib->type == 'custom' || $lib->type == 'mine') $this->view->spaces = $this->docZen->getAllSpaces($lib->type == 'mine' ? 'onlymine' : 'nomine');
  929. $this->docZen->setObjectsForEdit($lib->type, $objectID);
  930. $this->view->title = $lib->name . $this->lang->hyphen . $this->lang->doc->edit;
  931. $this->view->doc = $doc;
  932. $this->view->optionMenu = $this->loadModel('tree')->getOptionMenu($libID, 'doc', 0);
  933. $this->view->type = $lib->type;
  934. $this->view->libs = $libPairs;
  935. $this->view->lib = $lib;
  936. $this->view->libID = $libID;
  937. $this->view->libTree = $this->doc->getLibTree($libID, $libs, $objectType, $moduleID, (int)$objectID, '', 0, $docID);
  938. $this->view->groups = $this->loadModel('group')->getPairs();
  939. $this->view->users = $this->user->getPairs('noletter|noclosed|nodeleted', $doc->users);
  940. $this->view->files = $this->loadModel('file')->getByObject('doc', $docID);
  941. $this->view->objectType = $objectType;
  942. $this->view->object = $object;
  943. $this->view->objectID = $objectID;
  944. $this->view->objectDropdown = $objectDropdown;
  945. $this->view->moduleID = $moduleID;
  946. $this->view->spaceType = $objectType;
  947. $this->view->productID = $doc->product;
  948. $this->view->projectID = $doc->project;
  949. $this->view->executionID = $doc->execution;
  950. $this->view->linkParams = "objectID={$objectID}&%s&browseType=&orderBy=status,id_desc&param=0";
  951. $this->view->otherEditing = $this->doc->checkOtherEditing($docID);
  952. $this->display();
  953. }
  954. /**
  955. * 删除一个文档。
  956. * Delete a doc.
  957. *
  958. * @param int $docID
  959. * @access public
  960. * @return void
  961. */
  962. public function delete($docID)
  963. {
  964. $this->doc->delete(TABLE_DOC, $docID);
  965. /* Delete doc files. */
  966. $doc = $this->doc->getByID($docID);
  967. if($doc->files) $this->doc->deleteFiles(array_keys($doc->files));
  968. if(dao::isError()) $this->send(array('result' => 'fail', 'message' => dao::getError()));
  969. return $this->sendSuccess(array('load' => $this->session->docList ? $this->session->docList : $this->createLink('doc', 'index')));
  970. }
  971. /**
  972. * 删除一个文档模板。
  973. * Delete a doctemplate.
  974. *
  975. * @param int $templateID
  976. * @access public
  977. * @return void
  978. */
  979. public function deleteTemplate($templateID)
  980. {
  981. $this->doc->deleteTemplate($templateID);
  982. /* Delete template files. */
  983. $template = $this->doc->getByID($templateID);
  984. if($template->files) $this->doc->deleteFiles(array_keys($template->files));
  985. if(dao::isError()) $this->send(array('result' => 'fail', 'message' => dao::getError()));
  986. $link = $this->createLink('doc', 'browseTemplate');
  987. return $this->sendSuccess(array('load' => $link));
  988. }
  989. /**
  990. * 收藏一个文档。
  991. * Collect a doc.
  992. *
  993. * @param int $objectID
  994. * @access public
  995. * @return void
  996. */
  997. public function collect($objectID)
  998. {
  999. $action = $this->doc->getActionByObject($objectID, 'collect');
  1000. if($action)
  1001. {
  1002. $this->doc->deleteAction($action->id);
  1003. $this->action->create('doc', $objectID, 'uncollected');
  1004. }
  1005. else
  1006. {
  1007. $this->doc->createAction($objectID, 'collect');
  1008. $this->action->create('doc', $objectID, 'collected');
  1009. }
  1010. if($this->viewType == 'json') $this->send(array('status' => $action ? 'no' : 'yes'));
  1011. return $this->send(array('result' => 'success', 'message' => $action ? $this->lang->doc->cancelCollection : $this->lang->doc->collectSuccess, 'load' => true, 'status' => $action ? 'no' : 'yes'));
  1012. }
  1013. /**
  1014. *
  1015. * AJAX: 获取对象的目录。
  1016. * Ajax get modules by object.
  1017. *
  1018. * @param string $objectType project|product|custom|mine
  1019. * @param int $objectID
  1020. * @param string $docType doc|api
  1021. * @param int $docID
  1022. * @param int $libID
  1023. * @access public
  1024. * @return void
  1025. */
  1026. public function ajaxGetModules($objectType, $objectID, $docType = 'doc', $docID = 0, $libID = 0)
  1027. {
  1028. if($objectType != 'mine' && empty($objectID)) return print(json_encode(array()));
  1029. if($docType == 'doc')
  1030. {
  1031. $unclosed = strpos($this->config->doc->custom->showLibs, 'unclosed') !== false ? 'unclosedProject' : '';
  1032. $libPairs = $this->doc->getLibs($objectType, $unclosed, '', (int)$objectID);
  1033. }
  1034. elseif($docType == 'api')
  1035. {
  1036. $libs = $this->doc->getApiLibs(0, $objectType, $objectID);
  1037. $libPairs = array();
  1038. foreach($libs as $lib) $libPairs[$lib->id] = $lib->name;
  1039. }
  1040. $libItems = array();
  1041. foreach($libPairs as $id => $name) $libItems[] = array('text' => $name, 'value' => $id, 'keys' => $name);
  1042. $moduleItems = array();
  1043. $libID = $libID ? $libID : key($libPairs);
  1044. if($libID)
  1045. {
  1046. $chapterAndDocs = $this->doc->getDocsOfLibs(array($libID), $objectType, $docID);
  1047. $modulePairs = empty($libID) ? array() : $this->loadModel('tree')->getOptionMenu($libID, 'doc', 0);
  1048. $nestedDocs = $this->doc->buildNestedDocs($chapterAndDocs, $modulePairs);
  1049. $moduleItems = array_merge(array(array('text' => '/', 'value' => 'm_0')), array_values($nestedDocs));
  1050. }
  1051. return print(json_encode(array('libs' => $libItems, 'modules' => $moduleItems)));
  1052. }
  1053. /**
  1054. *
  1055. * AJAX: 获取范围下的类型。
  1056. * Ajax get types of scope.
  1057. *
  1058. * @param int $libID
  1059. * @access public
  1060. * @return json
  1061. */
  1062. public function ajaxGetScopeTypes($libID = 0)
  1063. {
  1064. $optionMenu = $this->loadModel('tree')->getOptionMenu($libID, 'docTemplate', 0, 'all', 'nodeleted', 'all');
  1065. $types = array();
  1066. foreach($optionMenu as $menuID => $menu)
  1067. {
  1068. if(empty($menuID)) continue;
  1069. $types[] = array('text' => $menu, 'value' => $menuID, 'keys' => $menu);
  1070. }
  1071. return print(json_encode($types));
  1072. }
  1073. /**
  1074. * AJAX: 通过空间类型获取文档库。
  1075. * AJAX: Get libs by type.
  1076. *
  1077. * @param string $type mine|product|project|nolink|custom
  1078. * @param string $docType doc|api
  1079. * @access public
  1080. * @return void
  1081. * @param string $extra
  1082. */
  1083. public function ajaxGetLibsByType($type, $docType = 'doc', $extra = '')
  1084. {
  1085. $libPairs = array();
  1086. if($docType == 'doc')
  1087. {
  1088. $unclosed = strpos($this->config->doc->custom->showLibs, 'unclosed') !== false ? 'unclosedProject' : '';
  1089. if($extra) $unclosed .= ",$extra";
  1090. $libPairs = $this->doc->getLibs($type, $unclosed);
  1091. }
  1092. elseif($docType == 'api')
  1093. {
  1094. $libs = $this->doc->getApiLibs(0, 'nolink');
  1095. $libPairs = array();
  1096. foreach($libs as $libID => $lib) $libPairs[$libID] = $lib->name;
  1097. }
  1098. $libItems = array();
  1099. foreach($libPairs as $id => $name) $libItems[] = array('text' => $name, 'value' => $id, 'keys' => $name);
  1100. $moduleItems = array();
  1101. $libID = key($libPairs);
  1102. if($libID)
  1103. {
  1104. $optionMenu = $this->loadModel('tree')->getOptionMenu($libID, $docType, 0);
  1105. foreach($optionMenu as $id => $name) $moduleItems[] = array('text' => $name, 'value' => $id, 'keys' => $name);
  1106. }
  1107. return print(json_encode(array('libs' => $libItems, 'modules' => $moduleItems)));
  1108. }
  1109. /**
  1110. * Ajax: 获取白名单。
  1111. * Ajax: Get whitelist.
  1112. *
  1113. * @param int $doclibID
  1114. * @param string $acl open|custom|private
  1115. * @param string $control user|group
  1116. * @param int $docID
  1117. * @access public
  1118. * @return string
  1119. */
  1120. public function ajaxGetWhitelist($doclibID, $acl = '', $control = '', $docID = 0)
  1121. {
  1122. $doclib = $this->doc->getLibByID($doclibID);
  1123. $users = $this->user->getPairs('noletter|noempty|noclosed');
  1124. if($control == 'group')
  1125. {
  1126. if($doclib->acl == 'private') return print('private');
  1127. $groupItems = array();
  1128. $groups = $this->loadModel('group')->getPairs();
  1129. foreach($groups as $groupID => $groupName) $groupItems[] = array('text' => $groupName, 'value' => $groupID, 'keys' => $groupName);
  1130. return print(json_encode($groupItems));
  1131. }
  1132. if($doclib->acl == 'private') return print('private');
  1133. $userItems = array();
  1134. foreach($users as $account => $realname)
  1135. {
  1136. if($doclib->acl == 'private' && strpos($doclib->users, (string)$account) === false ) unset($users[$account]);
  1137. $userItems[] = array('text' => $realname, 'value' => $account, 'keys' => $realname);
  1138. }
  1139. return print(json_encode($userItems));
  1140. }
  1141. /**
  1142. * 附件库。
  1143. * Show files.
  1144. *
  1145. * @param string $type
  1146. * @param int $objectID
  1147. * @param string $viewType
  1148. * @param string $browseType
  1149. * @param int $param
  1150. * @param string $orderBy
  1151. * @param int $recTotal
  1152. * @param int $recPerPage
  1153. * @param int $pageID
  1154. * @param string $searchTitle
  1155. * @access public
  1156. * @return void
  1157. */
  1158. public function showFiles($type, $objectID, $viewType = '', $browseType = '', $param = 0, $orderBy = 'id_desc', $recTotal = 0, $recPerPage = 20, $pageID = 1, $searchTitle = '')
  1159. {
  1160. $this->loadModel('file');
  1161. if(empty($viewType)) $viewType = !empty($_COOKIE['docFilesViewType']) ? $this->cookie->docFilesViewType : 'list';
  1162. helper::setcookie('docFilesViewType', $viewType, $this->config->cookieLife, $this->config->webRoot, '', $this->config->cookieSecure, true);
  1163. $objects = $this->doc->getOrderedObjects($type, 'nomerge', $objectID);
  1164. list($libs, $libID, $object, $objectID, $objectDropdown) = $this->doc->setMenuByType($type, $objectID, 0);
  1165. $object = $this->doc->getObjectByID($type, $objectID);
  1166. if(empty($_POST) && !empty($searchTitle)) $this->post->title = $searchTitle;
  1167. $this->session->set('storyList', $this->app->getURI(true), 'doc');
  1168. $this->session->set('bugList', $this->app->getURI(true), 'doc');
  1169. /* Load pager. */
  1170. $rawMethod = $this->app->rawMethod;
  1171. $this->app->rawMethod = 'showFiles';
  1172. $this->app->loadClass('pager', $static = true);
  1173. $pager = new pager($recTotal, $recPerPage, $pageID);
  1174. $this->app->rawMethod = $rawMethod;
  1175. $files = $this->doc->getLibFiles($type, $objectID, $browseType, (int)$param, $orderBy, $pager);
  1176. $fileIcon = $this->doc->getFileIcon($files);
  1177. $sourcePairs = $this->doc->getFileSourcePairs($files);
  1178. if($this->app->tab != 'doc')
  1179. {
  1180. $objectVar = $this->app->tab . 'ID';
  1181. $this->view->{$objectVar} = $objectID;
  1182. }
  1183. $this->docZen->buildSearchFormForShowFiles($type, $objectID, $viewType, $param);
  1184. $this->view->title = $object->name;
  1185. $this->view->type = $type;
  1186. $this->view->object = $object;
  1187. $this->view->files = $this->docZen->processFiles($files, $fileIcon, $sourcePairs);
  1188. $this->view->fileIcon = $fileIcon;
  1189. $this->view->sourcePairs = $sourcePairs;
  1190. $this->view->users = $this->loadModel('user')->getPairs('noletter');
  1191. $this->view->pager = $pager;
  1192. $this->view->viewType = $viewType;
  1193. $this->view->orderBy = $orderBy;
  1194. $this->view->objectID = $objectID;
  1195. $this->view->canBeChanged = common::canModify($type, $object); // Determines whether an object is editable.
  1196. $this->view->summary = $this->doc->summary($files);
  1197. $this->view->libTree = $this->doc->getLibTree(0, $libs, $type, 0, $objectID);
  1198. $this->view->objectDropdown = $objectDropdown;
  1199. $this->view->searchTitle = $searchTitle;
  1200. $this->view->linkParams = "objectID=$objectID&%s&browseType=&orderBy=status,id_desc&param=0";
  1201. $this->view->spaceType = $type;
  1202. $this->view->objectType = $type;
  1203. $this->view->browseType = $browseType;
  1204. $this->view->param = $param;
  1205. $this->view->libID = 0;
  1206. $this->view->moduleID = 0;
  1207. $this->display();
  1208. }
  1209. /**
  1210. * 文档详情页面。
  1211. * Document details page.
  1212. *
  1213. * @param string|int $docID
  1214. * @param int $version
  1215. * @access public
  1216. * @return void
  1217. */
  1218. public function view($docID = 0, $version = 0)
  1219. {
  1220. $isApi = is_string($docID) && strpos($docID, 'api.') === 0;
  1221. $docID = $isApi ? (int)str_replace('api.', '', $docID) : (int)$docID;
  1222. $doc = $isApi ? $this->loadModel('api')->getByID($docID, $version) : $this->doc->getByID($docID, $version, true);
  1223. $docParam = $version ? ($docID . '_' . $version) : $docID;
  1224. if($isApi) $docParam = 'api.' . $docParam;
  1225. if(!$doc || !isset($doc->id))
  1226. {
  1227. if(defined('RUN_MODE') && RUN_MODE == 'api') return $this->send(array('status' => 'fail', 'code' => 404, 'message' => '404 Not found'));
  1228. return $this->sendError($this->lang->notFound, $this->inlink('index'));
  1229. }
  1230. $_SESSION["doc_{$doc->id}_nopriv"] = '';
  1231. if(!$isApi && !$this->doc->checkPrivDoc($doc))
  1232. {
  1233. $user = $this->loadModel('user')->getByID($doc->addedBy);
  1234. $realname = $user->deleted ? $user->account : $user->realname;
  1235. $errorMessage = empty($_SESSION["doc_{$doc->id}_nopriv"]) ? sprintf($this->lang->doc->cannotView, $realname) : $_SESSION["doc_{$doc->id}_nopriv"];
  1236. unset($_SESSION["doc_{$doc->id}_nopriv"]);
  1237. return $this->sendError($errorMessage, inlink('index'));
  1238. }
  1239. unset($_SESSION["doc_{$doc->id}_nopriv"]);
  1240. if(!empty($doc->templateType))
  1241. {
  1242. echo $this->fetch('doc', 'browseTemplate', "libID=$doc->lib&type=all&docID=$docParam&orderBy=id_desc&recPerPage=20&pageID=1&mode=view");
  1243. return;
  1244. }
  1245. $lib = $this->doc->getLibByID((int)$doc->lib);
  1246. $objectType = isset($lib->type) ? $lib->type : 'custom';
  1247. if($objectType == 'api')
  1248. {
  1249. if(isset($lib->product) && $lib->product) list($objectType, $objectID) = array('product', $lib->product);
  1250. if(isset($lib->project) && $lib->project) list($objectType, $objectID) = array('project', $lib->project);
  1251. }
  1252. else
  1253. {
  1254. if($this->app->tab === 'project' && $objectType === 'execution') $objectType = 'project';
  1255. $objectID = $this->doc->getObjectIDByLib($lib, $objectType);
  1256. }
  1257. /* Get doc. */
  1258. if($docID) $this->doc->createAction($docID, 'view');
  1259. $this->view->title = $doc->title;
  1260. $libID = isset($lib->id) ? $lib->id : 0;
  1261. echo $this->fetch('doc', 'app', "type=$objectType&spaceID=$objectID&libID=$libID&moduleID=$doc->module&docID=$docParam&mode=view");
  1262. }
  1263. /**
  1264. * 产品/项目/执行/团队空间。
  1265. * ProductSpace/ProjectSpace/ExecutionSpace/TeamSpace.
  1266. *
  1267. * @param string $type custom|product|project|execution|doctemplate
  1268. * @param int $objectID
  1269. * @param int $libID
  1270. * @param int $moduleID
  1271. * @param string $browseType all|draft|bysearch
  1272. * @param string $orderBy
  1273. * @param int $param
  1274. * @param int $recTotal
  1275. * @param int $recPerPage
  1276. * @param int $pageID
  1277. * @access public
  1278. * @return void
  1279. */
  1280. public function tableContents($type = 'custom', $objectID = 0, $libID = 0, $moduleID = 0, $browseType = 'all', $orderBy = 'order_asc', $param = 0, $recTotal = 0, $recPerPage = 20, $pageID = 1)
  1281. {
  1282. $this->docZen->setSpacePageStorage($type, $browseType, $objectID, $libID, $moduleID, $param);
  1283. if($moduleID) $libID = $this->tree->getById($moduleID)->root;
  1284. $isFirstLoad = $libID == 0 ? true : false;
  1285. if(empty($browseType)) $browseType = 'all';
  1286. $libData = $this->doc->setMenuByType($type, $objectID, $libID);
  1287. if(is_string($libData)) return $this->locate($libData);
  1288. list($libs, $libID, $object, $objectID, $objectDropdown) = $libData;
  1289. $libID = (int)$libID;
  1290. $lib = $this->doc->getLibByID($libID);
  1291. $libType = isset($lib->type) && $lib->type == 'api' ? 'api' : 'lib';
  1292. /* Build the search form. */
  1293. $queryID = $browseType == 'bySearch' ? $param : 0;
  1294. $queryID = $queryID == 'myQueryID' ? 0 : $queryID;
  1295. $params = "objectID={$objectID}&libID={$libID}&moduleID=0&browseType=bySearch&orderBy={$orderBy}&param=myQueryID";
  1296. if($this->app->rawMethod == 'tablecontents') $params = "type={$type}&" . $params;
  1297. $actionURL = $this->createLink($this->app->rawModule, $this->app->rawMethod, $params);
  1298. if($libType == 'api') $this->loadModel('api')->buildSearchForm($lib, $queryID, $actionURL, $libs, $type);
  1299. if($libType != 'api') $this->doc->buildSearchForm($libID, $libs, $queryID, $actionURL, $type);
  1300. $this->docZen->assignApiVarForSpace($type, $browseType, $libType, $libID, $libs, $objectID, $moduleID, $queryID, $orderBy, $param, $recTotal, $recPerPage, $pageID);
  1301. /* For product drop menu. */
  1302. if(in_array($type, array('product', 'project', 'execution')))
  1303. {
  1304. $objectKey = $type . 'ID';
  1305. $this->view->$objectKey = $objectID;
  1306. }
  1307. $isOrderByOrder = $orderBy == 'order_asc';
  1308. $isNotCustomLib = $lib && !($lib->type == 'custom' && $lib->parent == 0);
  1309. $canUpdateOrder = $isOrderByOrder && $isNotCustomLib && common::hasPriv('doc', 'sortDoc');
  1310. $this->view->title = $type == 'custom' ? $this->lang->doc->tableContents : $object->name . $this->lang->hyphen . $this->lang->doc->tableContents;
  1311. $this->view->type = $type;
  1312. $this->view->objectType = $type;
  1313. $this->view->spaceType = $type;
  1314. $this->view->browseType = $browseType;
  1315. $this->view->isFirstLoad = $isFirstLoad;
  1316. $this->view->param = $queryID;
  1317. $this->view->users = $this->user->getPairs('noletter');
  1318. $this->view->libTree = $this->doc->getLibTree($libID, $libs, $type, $moduleID, $objectID, $browseType, (int)$param);
  1319. $this->view->libID = $libID;
  1320. $this->view->moduleID = $moduleID;
  1321. $this->view->objectDropdown = $objectDropdown;
  1322. $this->view->lib = $lib;
  1323. $this->view->libType = $libType;
  1324. $this->view->objectID = $objectID;
  1325. $this->view->orderBy = $orderBy;
  1326. $this->view->release = $browseType == 'byrelease' ? $param : 0;
  1327. $this->view->exportMethod = $libType == 'api' ? 'export' : $type . '2export';
  1328. $this->view->linkParams = "objectID={$objectID}&%s&browseType=&orderBy={$orderBy}&param=0";
  1329. $this->view->canUpdateOrder = $canUpdateOrder;
  1330. $this->display();
  1331. }
  1332. /**
  1333. * 产品空间。
  1334. * Product space.
  1335. *
  1336. * @param int $objectID
  1337. * @param int $libID
  1338. * @param int $moduleID
  1339. * @param string $browseType all|draft|bysearch
  1340. * @param string $orderBy
  1341. * @param int $param
  1342. * @param int $recTotal
  1343. * @param int $recPerPage
  1344. * @param int $pageID
  1345. * @access public
  1346. * @return void
  1347. * @param string $mode
  1348. * @param int $docID
  1349. * @param string $search
  1350. */
  1351. public function productSpace($objectID = 0, $libID = 0, $moduleID = 0, $browseType = 'all', $orderBy = '', $param = 0, $recTotal = 0, $recPerPage = 20, $pageID = 1, $mode = '', $docID = 0, $search = '')
  1352. {
  1353. $noSpace = $this->app->tab != 'doc';
  1354. $mode = empty($mode) && $noSpace ? 'list' : $mode;
  1355. echo $this->fetch('doc', 'app', "type=product&spaceID=$objectID&libID=$libID&moduleID=$moduleID&docID=$docID&mode=$mode&orderBy=$orderBy&recTotal=$recTotal&recPerPage=$recPerPage&pageID=$pageID&filterType=$browseType&search=$search&noSpace=$noSpace");
  1356. }
  1357. /**
  1358. * 项目空间。
  1359. * Project space.
  1360. *
  1361. * @param int $objectID
  1362. * @param int $libID
  1363. * @param int $moduleID
  1364. * @param string $browseType all|draft|bysearch
  1365. * @param string $orderBy
  1366. * @param int $param
  1367. * @param int $recTotal
  1368. * @param int $recPerPage
  1369. * @param int $pageID
  1370. * @access public
  1371. * @return void
  1372. * @param string $mode
  1373. * @param int $docID
  1374. * @param string $search
  1375. */
  1376. public function projectSpace($objectID = 0, $libID = 0, $moduleID = 0, $browseType = 'all', $orderBy = '', $param = 0, $recTotal = 0, $recPerPage = 20, $pageID = 1, $mode = '', $docID = 0, $search = '')
  1377. {
  1378. $noSpace = $this->app->tab != 'doc';
  1379. $mode = empty($mode) && $noSpace ? 'list' : $mode;
  1380. echo $this->fetch('doc', 'app', "type=project&spaceID=$objectID&libID=$libID&moduleID=$moduleID&docID=$docID&mode=$mode&orderBy=$orderBy&recTotal=$recTotal&recPerPage=$recPerPage&pageID=$pageID&filterType=$browseType&search=$search&noSpace=$noSpace");
  1381. }
  1382. /**
  1383. * 团队空间。
  1384. * Team space.
  1385. *
  1386. * @param int $objectID
  1387. * @param int $libID
  1388. * @param int $moduleID
  1389. * @param string $browseType all|draft|bysearch
  1390. * @param string $orderBy
  1391. * @param int $param
  1392. * @param int $recTotal
  1393. * @param int $recPerPage
  1394. * @param int $pageID
  1395. * @access public
  1396. * @return void
  1397. * @param string $mode
  1398. * @param int $docID
  1399. * @param string $search
  1400. */
  1401. public function teamSpace($objectID = 0, $libID = 0, $moduleID = 0, $browseType = 'all', $orderBy = '', $param = 0, $recTotal = 0, $recPerPage = 20, $pageID = 1, $mode = '', $docID = 0, $search = '')
  1402. {
  1403. $this->docZen->initLibForTeamSpace();
  1404. echo $this->fetch('doc', 'app', "type=custom&spaceID=$objectID&libID=$libID&moduleID=$moduleID&docID=$docID&mode=$mode&orderBy=$orderBy&recTotal=$recTotal&recPerPage=$recPerPage&pageID=$pageID&filterType=$browseType&search=$search");
  1405. }
  1406. /**
  1407. * 设置选择文档库类型的范围。
  1408. * Set the scope of the document library type to be selected.
  1409. *
  1410. * @param string $objectType
  1411. * @param string $params
  1412. * @param string $from
  1413. * @access public
  1414. * @return void
  1415. */
  1416. public function selectLibType($objectType = 'mine', $params = '', $from = '')
  1417. {
  1418. if($_POST)
  1419. {
  1420. $response = array();
  1421. $libID = $_POST['lib'];
  1422. $moduleID = $_POST['module'];
  1423. $rootSpace = $_POST['rootSpace'];
  1424. $docType = isset($_POST['type']) ? $_POST['type'] : 'doc';
  1425. if(empty($libID)) return $this->send(array('result' => 'fail', 'message' => sprintf($this->lang->error->notempty, $this->lang->doc->lib)));
  1426. $spaceID = 0;
  1427. if(in_array($rootSpace, array('mine', 'custom', 'product', 'project')))
  1428. {
  1429. $methodList = array('mine' => 'mySpace', 'custom' => 'teamSpace', 'product' => 'productSpace', 'project' => 'projectSpace');
  1430. $spaceID = $_POST[$rootSpace];
  1431. $method = $methodList[$rootSpace];
  1432. if($docType == 'doc') $url = $this->createLink('doc', $method, "objectID=$spaceID&libID=$libID&moduleID=$moduleID&browseType=all&params=0&orderBy=&recTotal=0&recPerPage=20&pageID=1&mode=create");
  1433. else $url = helper::createLink('api', 'create', "libID=$libID&moduleID=$moduleID&space=$rootSpace");
  1434. }
  1435. elseif($rootSpace == 'api')
  1436. {
  1437. $url = helper::createLink('api', 'create', "libID=$libID&moduleID=$moduleID&space=$rootSpace");
  1438. }
  1439. $response['result'] = 'success';
  1440. $response['closeModal'] = true;
  1441. $response['callback'] = "redirectParentWindow(\"{$url}\", \"{$from}\", \"{$spaceID}\", \"{$libID}\", \"{$moduleID}\")";
  1442. return $this->send($response);
  1443. }
  1444. $spaceList = $this->lang->doc->spaceList;
  1445. $typeList = $this->lang->doc->types;
  1446. if(!common::hasPriv('doc', 'create')) unset($spaceList['mine'], $spaceList['custom'], $typeList['doc']);
  1447. if(!common::hasPriv('doc', 'mySpace')) unset($spaceList['mine']);
  1448. if(!common::hasPriv('doc', 'productSpace')) unset($spaceList['product']);
  1449. if(!common::hasPriv('doc', 'projectSpace')) unset($spaceList['project']);
  1450. if(!common::hasPriv('doc', 'teamSpace')) unset($spaceList['custom']);
  1451. if(!common::hasPriv('api', 'index')) unset($spaceList['api']);
  1452. if(!common::hasPriv('api', 'create')) unset($spaceList['api'], $typeList['api']);
  1453. if($this->config->vision == 'lite') unset($spaceList['api'], $spaceList['product'], $typeList['api']);
  1454. $params = helper::safe64Decode($params);
  1455. parse_str($params, $params);
  1456. $this->view->params = $params;
  1457. $this->view->objectType = $objectType;
  1458. $this->view->spaceList = $spaceList;
  1459. $this->view->typeList = $typeList;
  1460. $this->view->from = $from;
  1461. $this->display();
  1462. }
  1463. /**
  1464. * Ajax: 根据对象类型设置下拉菜单。
  1465. * Ajax: Set the drop-down menu according to the object type.
  1466. *
  1467. * @param string $objectType product|project
  1468. * @param int $objectID
  1469. * @param string $module
  1470. * @param string $method
  1471. * @access public
  1472. * @return void
  1473. */
  1474. public function ajaxGetDropMenu($objectType, $objectID, $module, $method)
  1475. {
  1476. list($myObjects, $normalObjects, $closedObjects) = $this->doc->getOrderedObjects($objectType, 'nomerge', $objectID);
  1477. $libData = $this->doc->setMenuByType($objectType, $objectID, 0);
  1478. $this->view->objectType = $objectType;
  1479. $this->view->objectID = $objectID;
  1480. $this->view->libID = !empty($libData[1]) ? $libData[1] : 0;
  1481. $this->view->module = $module;
  1482. $this->view->method = $method == 'view' ? $objectType.'space' : $method;
  1483. $this->view->normalObjects = $myObjects + $normalObjects;
  1484. $this->view->closedObjects = $closedObjects;
  1485. $this->view->objectsPinYin = common::convert2Pinyin($myObjects + $normalObjects + $closedObjects);
  1486. $this->display();
  1487. }
  1488. /**
  1489. * Ajax: 获取空间的下拉数据。
  1490. * Ajax: Get the space drop down.
  1491. *
  1492. * @param int $libID
  1493. * @param string $module
  1494. * @param string $method
  1495. * @access public
  1496. * @return void
  1497. * @param string $extra
  1498. */
  1499. public function ajaxGetSpaceMenu($libID, $module, $method, $extra = 'nomine')
  1500. {
  1501. $this->view->libID = $libID;
  1502. $this->view->module = $module;
  1503. $this->view->method = $method;
  1504. $this->view->extra = $extra;
  1505. $this->view->spaces = $this->docZen->getAllSpaces($extra);
  1506. $this->display();
  1507. }
  1508. /**
  1509. * Ajax: 获取执行下拉数据。
  1510. * Ajax: Get the execution drop down by the projectID.
  1511. *
  1512. * @param int $projectID
  1513. * @access public
  1514. * @return string
  1515. */
  1516. public function ajaxGetExecution($projectID)
  1517. {
  1518. $json = array();
  1519. $items = array();
  1520. $executionPairs = $this->execution->getPairs($projectID, 'all', 'multiple,leaf,noprefix');
  1521. foreach($executionPairs as $id => $name) $items[] = array('text' => $name, 'value' => $id, 'keys' => $name);
  1522. $json['items'] = $items;
  1523. $json['project'] = $this->project->getByID($projectID);
  1524. return print(json_encode($json));
  1525. }
  1526. /**
  1527. * 编辑一个目录。
  1528. * Edit a catalog.
  1529. *
  1530. * @param int $moduleID
  1531. * @param string $type doc|api
  1532. * @access public
  1533. * @return void
  1534. */
  1535. public function editCatalog($moduleID, $type)
  1536. {
  1537. echo $this->fetch('tree', 'edit', "moduleID={$moduleID}&type={$type}");
  1538. }
  1539. /**
  1540. * 删除一个目录。
  1541. * Delete a catalog.
  1542. *
  1543. * @param int $moduleID
  1544. * @access public
  1545. * @return void
  1546. */
  1547. public function deleteCatalog($moduleID)
  1548. {
  1549. echo $this->fetch('tree', 'delete', "moduleID={$moduleID}&confirm=yes");
  1550. }
  1551. /**
  1552. * 设置左侧树中是否显示文档。
  1553. * Set documents are show or hidden in the left tree.
  1554. *
  1555. * @access public
  1556. * @return void
  1557. */
  1558. public function displaySetting()
  1559. {
  1560. $this->loadModel('setting');
  1561. if($_POST)
  1562. {
  1563. $this->setting->setItem($this->app->user->account . '.doc.showDoc', $this->post->showDoc);
  1564. return $this->sendSuccess(array('load' => true, 'closeModal' => true));
  1565. }
  1566. $showDoc = $this->setting->getItem('owner=' . $this->app->user->account . '&module=doc&key=showDoc');
  1567. $this->view->showDoc = $showDoc === '0' ? '0' : '1';
  1568. $this->display();
  1569. }
  1570. /**
  1571. * 文档库排序
  1572. * Doclib sorting.
  1573. *
  1574. * @access public
  1575. * @return void
  1576. */
  1577. public function sortDoclib()
  1578. {
  1579. if($_POST)
  1580. {
  1581. $orders = $_POST['orders'];
  1582. if(is_string($orders)) $orders = json_decode($orders, true);
  1583. foreach($orders as $id => $order) $this->doc->updateDoclibOrder($id, (int)$order);
  1584. if(dao::isError()) return $this->send(array('result' => 'fail', 'message' => dao::getError()));
  1585. return $this->send(array('result' => 'success', 'orders' => $orders));
  1586. }
  1587. }
  1588. /**
  1589. * 文档排序
  1590. * Doc sorting.
  1591. *
  1592. * @access public
  1593. * @return void
  1594. */
  1595. public function sortDoc()
  1596. {
  1597. if($_POST)
  1598. {
  1599. $orders = json_decode($this->post->orders, true);
  1600. asort($orders);
  1601. $orders = array_flip($orders);
  1602. /* Sort by sorted id list. */
  1603. $this->doc->updateDocOrder($orders);
  1604. if(dao::isError()) return $this->send(array('result' => 'fail', 'message' => dao::getError()));
  1605. return $this->send(array('result' => 'success'));
  1606. }
  1607. }
  1608. /**
  1609. * 目录排序
  1610. * Catalog sorting.
  1611. *
  1612. * @access public
  1613. * @return void
  1614. */
  1615. public function sortCatalog()
  1616. {
  1617. if($_POST)
  1618. {
  1619. $orders = $_POST['orders'];
  1620. $type = isset($_POST['type']) ? $_POST['type'] : 'doc';
  1621. if(is_string($orders)) $orders = json_decode($orders, true);
  1622. foreach($orders as $id => $order) $this->doc->updateOrder($id, (int)$order, $type);
  1623. if(dao::isError()) return $this->send(array('result' => 'fail', 'message' => dao::getError()));
  1624. return $this->send(array('result' => 'success'));
  1625. }
  1626. }
  1627. /**
  1628. * 删除文档附件。
  1629. * Delete file for doc.
  1630. *
  1631. * @param int $docID
  1632. * @param int $fileID
  1633. * @param string $confirm
  1634. * @access public
  1635. * @return void
  1636. */
  1637. public function deleteFile($docID, $fileID, $confirm = 'no')
  1638. {
  1639. $this->loadModel('file');
  1640. if($confirm == 'no')
  1641. {
  1642. $formUrl = inlink('deleteFile', "docID={$docID}&fileID={$fileID}&confirm=yes");
  1643. return $this->send(array('result' => 'fail', 'callback' => "zui.Modal.confirm('{$this->lang->file->confirmDelete}').then((res) => {if(res) $.ajaxSubmit({url: '$formUrl'});});"));
  1644. }
  1645. else
  1646. {
  1647. $this->doc->updateDocFile($docID, $fileID);
  1648. if(dao::isError()) return $this->send(array('result' => 'fail', 'message' => dao::getError()));
  1649. $file = $this->file->getById($fileID);
  1650. $this->action->create($file->objectType, $file->objectID, 'deletedFile', '', $file->title);
  1651. return $this->send(array('result' => 'success', 'message' => $this->lang->saveSuccess, 'load' => true));
  1652. }
  1653. }
  1654. /**
  1655. * 移动文档库
  1656. * Move Lib.
  1657. *
  1658. * @param int $libID
  1659. * @param string $targetSpace [int]
  1660. * @access public
  1661. * @return void
  1662. */
  1663. public function moveLib($libID, $targetSpace = '')
  1664. {
  1665. $lib = $this->doc->getLibByID($libID);
  1666. if(empty($targetSpace)) $targetSpace = $this->doc->getLibTargetSpace($lib);
  1667. $spaceType = $this->doc->getParamFromTargetSpace($targetSpace, 'type');
  1668. if(!empty($lib->main)) return $this->send(array('result' => 'fail', 'message' => $this->lang->doc->errorEditSystemDoc));
  1669. if(!empty($_POST))
  1670. {
  1671. $data = form::data()
  1672. ->setIF($this->post->acl == 'open', 'groups', '')
  1673. ->setIF($this->post->acl == 'open', 'users', '')
  1674. ->get();
  1675. if(dao::isError()) return $this->send(array('result' => 'fail', 'message' => dao::getError()));
  1676. $this->doc->moveLib($libID, $data);
  1677. if(dao::isError()) return $this->send(array('result' => 'fail', 'message' => dao::getError()));
  1678. $spaceTypeChanged = $spaceType != $lib->type;
  1679. return $this->docZen->responseAfterMove($this->post->space, $libID, 0, $spaceTypeChanged);
  1680. }
  1681. $this->docZen->setAclForCreateLib($spaceType);
  1682. $this->view->title = $this->lang->doc->moveLibAction;
  1683. $this->view->spaces = $this->doc->getAllSubSpaces('all');
  1684. $this->view->lib = $lib;
  1685. $this->view->targetSpace = $targetSpace;
  1686. $this->view->libType = $spaceType;
  1687. $this->view->hasOthersDoc = $this->doc->hasOthersDoc($lib);
  1688. $this->view->groups = $this->loadModel('group')->getPairs();
  1689. $this->view->users = $this->loadModel('user')->getPairs('nocode|noclosed');
  1690. $this->display();
  1691. }
  1692. /**
  1693. * 移动文档
  1694. * Move Document.
  1695. *
  1696. * @param int $docID
  1697. * @param int $libID
  1698. * @param string $spaceType
  1699. * @param string $space
  1700. * @access public
  1701. * @return void
  1702. */
  1703. public function moveDoc($docID, $libID = 0, $spaceType = '', $space = '')
  1704. {
  1705. if($spaceType == 'quick')
  1706. {
  1707. $libID = 0;
  1708. $space = $spaceType = '';
  1709. }
  1710. $doc = $this->doc->getByID($docID);
  1711. if(empty($libID)) $libID = (int)$doc->lib;
  1712. $lib = $this->doc->getLibByID($libID);
  1713. if(empty($space))
  1714. {
  1715. if($lib->parent)
  1716. {
  1717. $space = $lib->parent;
  1718. }
  1719. else
  1720. {
  1721. if($lib->product) $space = $lib->product;
  1722. if($lib->project) $space = $lib->project;
  1723. }
  1724. }
  1725. if(empty($spaceType))
  1726. {
  1727. if($lib->parent)
  1728. {
  1729. $spaceType = $this->doc->getSpaceType($space);
  1730. }
  1731. else
  1732. {
  1733. if($lib->product && $lib->type == 'product') $spaceType = 'product';
  1734. if($lib->project && $lib->type == 'project') $spaceType = 'project';
  1735. }
  1736. }
  1737. if(!empty($_POST))
  1738. {
  1739. /* parent带‘m_’前缀为目录。*/
  1740. if(isset($_POST['parent']) && strpos($_POST['parent'], 'm_') !== false)
  1741. {
  1742. $_POST['module'] = str_replace('m_', '', $_POST['parent']);
  1743. $_POST['parent'] = 0;
  1744. }
  1745. $data = form::data()
  1746. ->setIF($this->post->acl == 'open', 'groups', '')
  1747. ->setIF($this->post->acl == 'open', 'users', '')
  1748. ->setIF($this->post->acl == 'open', 'readGroups', '')
  1749. ->setIF($this->post->acl == 'open', 'readUsers', '')
  1750. ->setIF(in_array($spaceType, array('project', 'product')), $spaceType, $space)
  1751. ->setIF($spaceType != 'project', 'project', 0)
  1752. ->setIF($spaceType != 'product', 'product', 0)
  1753. ->get();
  1754. if(dao::isError()) return $this->send(array('result' => 'fail', 'message' => dao::getError()));
  1755. $changes = common::createChanges($doc, $data);
  1756. if($changes)
  1757. {
  1758. $this->doc->doUpdateDoc($docID, $data);
  1759. if(dao::isError()) return $this->send(array('result' => 'fail', 'message' => dao::getError()));
  1760. $actionID = $this->loadModel('action')->create('doc', $docID, 'Moved', '', json_encode(array('from' => $doc->lib, 'to' => $data->lib)));
  1761. $this->action->logHistory($actionID, $changes);
  1762. }
  1763. $spaceTypeChanged = $spaceType != $lib->type;
  1764. return $this->docZen->responseAfterMove($this->post->space, $data->lib, $docID, $spaceTypeChanged);
  1765. }
  1766. $projects = $this->loadModel('project')->getPairsByProgram(0, 'all', false, 'order_asc');
  1767. $products = $this->loadModel('product')->getPairs();
  1768. $executions = $this->loadModel('execution')->getPairs(0, 'all', 'multiple,leaf');
  1769. $libPairs = $this->doc->getLibPairs($spaceType, 'withObject', (int)$space, '', $products, $projects, $executions);
  1770. if($spaceType == 'project') $libPairs += $this->doc->getExecutionLibPairsByProject((int)$space, 'withObject', $executions);
  1771. if(!isset($libPairs[$libID])) $libID = (int)key($libPairs);
  1772. $chapterAndDocs = $this->doc->getDocsOfLibs(array($libID), $spaceType, $docID);
  1773. $modulePairs = empty($libID) ? array() : $this->loadModel('tree')->getOptionMenu($libID, 'doc', 0);
  1774. if(isset($doc) && !empty($doc->parent) && !isset($chapterAndDocs[$doc->parent])) $chapterAndDocs[$doc->parent] = $this->doc->fetchByID($doc->parent);
  1775. $chapterAndDocs = $this->doc->buildNestedDocs($chapterAndDocs, $modulePairs);
  1776. $this->view->docID = $docID;
  1777. $this->view->libID = $libID;
  1778. $this->view->spaceType = $spaceType;
  1779. $this->view->space = $space;
  1780. $this->view->doc = $doc;
  1781. $this->view->spaces = $this->doc->getAllSubSpaces($this->app->tab != 'doc' ? $this->app->tab : 'all');
  1782. $this->view->libPairs = $libPairs;
  1783. $this->view->optionMenu = $chapterAndDocs;
  1784. $this->view->groups = $this->loadModel('group')->getPairs();
  1785. $this->view->users = $this->loadModel('user')->getPairs('nocode|noclosed');
  1786. $this->display();
  1787. }
  1788. /**
  1789. * 移动文档模板
  1790. * Move document template.
  1791. *
  1792. * @param int $docID
  1793. * @access public
  1794. * @return void
  1795. */
  1796. public function moveTemplate($docID)
  1797. {
  1798. $doc = $this->doc->getByID($docID);
  1799. if(!empty($_POST))
  1800. {
  1801. $this->lang->doc->module = $this->lang->docTemplate->module;
  1802. $data = form::data()
  1803. ->setIF(!isset($_POST['lib']), 'lib', $doc->lib)
  1804. ->setIF(!isset($_POST['module']), 'module', $doc->module)
  1805. ->setIF(!isset($_POST['parent']), 'parent', $doc->parent)
  1806. ->setIF(!isset($_POST['acl']), 'acl', $doc->acl)
  1807. ->get();
  1808. $changes = common::createChanges($doc, $data);
  1809. if($changes)
  1810. {
  1811. $basicInfoChanged = false;
  1812. foreach($changes as $change)
  1813. {
  1814. if(in_array($change['field'], array('module', 'lib', 'acl'))) $basicInfoChanged = true;
  1815. }
  1816. $this->doc->doUpdateDoc($docID, $data, $basicInfoChanged);
  1817. if(dao::isError()) return $this->send(array('result' => 'fail', 'message' => dao::getError()));
  1818. $actionID = $this->loadModel('action')->create('docTemplate', $docID, 'Moved', '', json_encode(array('from' => $doc->lib, 'to' => $data->lib)));
  1819. $this->action->logHistory($actionID, $changes);
  1820. }
  1821. $newDoc = $this->doc->getByID($docID);
  1822. if(!$this->doc->checkPrivDoc($newDoc))
  1823. {
  1824. $link = $this->createLink('doc', 'browseTemplate', "libID={$doc->lib}&type=all&docID=0&orderBy=id_desc&recPerPage=20&pageID=1&mode=list");
  1825. return $this->send(array('result' => 'success', 'message' => $this->lang->saveSuccess, 'load' => $link, 'doc' => $newDoc));
  1826. }
  1827. $docAppAction = array('executeCommand', 'handleMovedDoc', array($docID, '1', $data->lib));
  1828. return $this->send(array('result' => 'success', 'message' => $this->lang->saveSuccess, 'closeModal' => true, 'docApp' => $docAppAction));
  1829. }
  1830. if(!empty($doc->parent))
  1831. {
  1832. $parentDoc = $this->doc->fetchByID($doc->parent);
  1833. $chapterAndDocs = $this->doc->getDocsOfLibs(array($doc->lib), 'template', $docID, true);
  1834. if(!isset($chapterAndDocs[$doc->parent])) $chapterAndDocs[$doc->parent] = $parentDoc;
  1835. $parentPath = trim($parentDoc->path, ',') . ",";
  1836. $topTemplate = substr($parentPath, 0, strpos($parentPath, ',')) ?: $doc->parent;
  1837. foreach($chapterAndDocs as $key => $template)
  1838. {
  1839. if(strpos(",{$template->path},", ",{$topTemplate},") === false) unset($chapterAndDocs[$key]);
  1840. }
  1841. $this->view->chapterAndDocs = $this->doc->buildNestedDocs($chapterAndDocs);
  1842. }
  1843. $scopeList = $this->doc->getTemplateScopes();
  1844. $this->view->scopeItems = $this->doc->getScopeItems($scopeList);
  1845. $this->view->doc = $doc;
  1846. $this->view->docID = $docID;
  1847. $this->view->modules = $this->loadModel('tree')->getOptionMenu((int)$doc->lib, 'docTemplate', 0, 'all', 'nodeleted', 'all');
  1848. $this->display();
  1849. }
  1850. /**
  1851. * Batch move document.
  1852. *
  1853. * @param string $type
  1854. * @param string $encodeDocIdList
  1855. * @param int $spaceID
  1856. * @param int $libID
  1857. * @param int $moduleID
  1858. * @access public
  1859. * @return void
  1860. */
  1861. public function batchMoveDoc($type, $encodeDocIdList, $spaceID, $libID = 0, $moduleID = 0)
  1862. {
  1863. $docIdList = json_decode(base64_decode($encodeDocIdList), true);
  1864. if(!$docIdList) $this->locate($this->createLink('doc', 'app', "type={$type}&spaceID={$spaceID}&libID={$libID}&moduleID={$moduleID}"));
  1865. $spaces = $this->doc->getAllSubSpaces();
  1866. if($type == 'quick')
  1867. {
  1868. list($type, $spaceID) = explode('.', key($spaces));
  1869. $spaceID = (int) $spaceID;
  1870. }
  1871. if($_POST)
  1872. {
  1873. $oldDocList = $this->doc->getDocsByIdList($docIdList);
  1874. $data = form::data()
  1875. ->setIF($type == 'mine' || $this->post->acl == 'open', 'groups', '')
  1876. ->setIF($type == 'mine' || $this->post->acl == 'open', 'users', '')
  1877. ->setIF(in_array($type, array('project', 'product')), $type, $spaceID)
  1878. ->get();
  1879. $this->doc->batchMoveDoc($data, $docIdList);
  1880. if(dao::isError()) return $this->send(array('result' => 'fail', 'message' => dao::getError()));
  1881. $this->docZen->recordBatchMoveActions($oldDocList, $data);
  1882. return $this->send(array('result' => 'success', 'message' => $this->lang->saveSuccess, 'closeModal' => true, 'docApp' => array('load', null, null, null, array('noLoading' => true, 'picks' => 'doc'))));
  1883. }
  1884. $projects = $this->loadModel('project')->getPairsByProgram(0, 'all', false, 'order_asc');
  1885. $products = $this->loadModel('product')->getPairs();
  1886. $executions = $this->loadModel('execution')->getPairs(0, 'all', 'multiple,leaf');
  1887. $libPairs = $this->doc->getLibPairs($type, 'withObject', $spaceID, '', $products, $projects, $executions);
  1888. if($type == 'project') $libPairs += $this->doc->getExecutionLibPairsByProject($spaceID, 'withObject', $executions);
  1889. if(!isset($libPairs[$libID])) $libID = (int)key($libPairs);
  1890. $docList = $this->doc->getByIdList($docIdList);
  1891. $docAclList = array_column($docList, 'acl');
  1892. $this->view->title = $this->lang->doc->batchMove;
  1893. $this->view->encodeDocIdList = $encodeDocIdList;
  1894. $this->view->type = $type;
  1895. $this->view->spaceID = $spaceID;
  1896. $this->view->libID = $libID;
  1897. $this->view->moduleID = $moduleID;
  1898. $this->view->spaces = $spaces;
  1899. $this->view->libPairs = $libPairs;
  1900. $this->view->optionMenu = $this->loadModel('tree')->getOptionMenu($libID, 'doc', 0);
  1901. $this->view->groups = $this->loadModel('group')->getPairs();
  1902. $this->view->users = $this->loadModel('user')->getPairs('nocode|noclosed');
  1903. $this->view->hasOpenDoc = in_array('open', $docAclList);
  1904. $this->display();
  1905. }
  1906. /**
  1907. * Ajax: 检查对象权限。
  1908. * Ajax check object priv.
  1909. *
  1910. * @param string $objectType
  1911. * @param int $objectID
  1912. * @access public
  1913. * @return void
  1914. */
  1915. public function ajaxCheckObjectPriv($objectType, $objectID)
  1916. {
  1917. $accounts = $this->post->users;
  1918. $object = $this->doc->getObjectByID($objectType, $objectID);
  1919. if(empty($object)) return print('');
  1920. if($object->acl == 'open') return print('');
  1921. $this->loadModel('user');
  1922. $userViews = $this->dao->select('*')->from(TABLE_USERVIEW)->where('account')->in($accounts)->fetchAll('account');
  1923. $userPairs = $this->dao->select('account,realname')->from(TABLE_USER)->where('account')->in($accounts)->fetchPairs('account', 'realname');
  1924. $denyUsers = array();
  1925. foreach($accounts as $account)
  1926. {
  1927. if(strpos(",{$this->app->company->admins}", ",{$account},") !== false) continue;
  1928. $userView = zget($userViews, $account, '');
  1929. if(empty($userView)) $userView = $this->user->computeUserView($account, true);
  1930. if($objectType == 'product' && isset($userView->products) && strpos(",{$userView->products},", ",{$objectID},") === false) $denyUsers[$account] = zget($userPairs, $account);
  1931. if($objectType == 'project' && isset($userView->projects) && strpos(",{$userView->projects},", ",{$objectID},") === false) $denyUsers[$account] = zget($userPairs, $account);
  1932. if($objectType == 'execution' && isset($userView->sprints) && strpos(",{$userView->sprints},", ",{$objectID},") === false) $denyUsers[$account] = zget($userPairs, $account);
  1933. }
  1934. if(empty($denyUsers)) return print('');
  1935. if(isset($this->lang->doc->whitelistDeny[$objectType])) return printf($this->lang->doc->whitelistDeny[$objectType], implode('、', $denyUsers));
  1936. }
  1937. /**
  1938. * Ajax: 检查库权限。
  1939. * Ajax check lib priv.
  1940. *
  1941. * @param int $libID
  1942. * @access public
  1943. * @return void
  1944. */
  1945. public function ajaxCheckLibPriv($libID)
  1946. {
  1947. $accounts = $this->post->users;
  1948. $lib = $this->doc->getLibByID($libID);
  1949. if(empty($lib)) return print('');
  1950. if($lib->acl == 'open') return print('');
  1951. if($lib->acl == 'default' && strpos("product,project,execution", $lib->type) !== false) return $this->ajaxCheckObjectPriv($lib->type, zget($lib, $lib->type, 0));
  1952. $authAccounts[$lib->addedBy] = $lib->addedBy;
  1953. if($lib->groups) $authAccounts += $this->loadModel('group')->getGroupAccounts(explode(',', $lib->groups));
  1954. if($lib->users)
  1955. {
  1956. foreach(array_filter(explode(',', $lib->users)) as $account) $authAccounts[$account] = $account;
  1957. }
  1958. $userPairs = $this->dao->select('account,realname')->from(TABLE_USER)->where('account')->in($accounts)->fetchPairs('account', 'realname');
  1959. $denyUsers = array();
  1960. foreach($accounts as $account)
  1961. {
  1962. if(strpos(",{$this->app->company->admins}", ",{$account},") !== false) continue;
  1963. if(!isset($authAccounts[$account])) $denyUsers[$account] = zget($userPairs, $account);
  1964. }
  1965. if(empty($denyUsers)) return print('');
  1966. if(isset($this->lang->doc->whitelistDeny['doc'])) return printf($this->lang->doc->whitelistDeny['doc'], implode('、', $denyUsers));
  1967. }
  1968. /**
  1969. * Doc app view.
  1970. * 文档应用视图。
  1971. *
  1972. * @param string $type
  1973. * @param int $spaceID
  1974. * @param int $libID
  1975. * @param int $moduleID
  1976. * @param mixed $docID
  1977. * @param string $mode
  1978. * @param string $orderBy
  1979. * @param int $recTotal
  1980. * @param int $recPerPage
  1981. * @param int $pageID
  1982. * @param string $filterType
  1983. * @param string $search
  1984. * @param string $param
  1985. * @access public
  1986. * @access public
  1987. * @return void
  1988. * @param bool $noSpace
  1989. */
  1990. public function app($type = 'mine', $spaceID = 0, $libID = 0, $moduleID = 0, $docID = 0, $mode = '', $orderBy = '', $recTotal = 0, $recPerPage = 20, $pageID = 1, $filterType = '', $search = '', $noSpace = false)
  1991. {
  1992. $isNotDocTab = $this->app->tab != 'doc';
  1993. if(empty($mode))
  1994. {
  1995. $showList = $noSpace || !empty($spaceID);
  1996. $mode = ($isNotDocTab || $type == 'execution' || $showList) ? 'list' : 'home';
  1997. }
  1998. $this->app->loadLang('file');
  1999. /* For product drop menu. */
  2000. if(!$isNotDocTab && $type == 'execution')
  2001. {
  2002. $execution = $this->loadModel('execution')->getByID($spaceID);
  2003. $type = 'project';
  2004. $spaceID = $execution->project;
  2005. }
  2006. if($isNotDocTab && in_array($type, array('product', 'project', 'execution')))
  2007. {
  2008. if($type == 'product' && $spaceID == 0) $spaceID = (int)$this->cookie->preProductID;
  2009. $this->doc->setMenuByType($type, $spaceID, $libID);
  2010. $objectKey = $type . 'ID';
  2011. $this->view->$objectKey = $spaceID;
  2012. $this->view->$type = $this->doc->fetchByID($spaceID, $type);
  2013. }
  2014. if($type == 'mine') $menuType = 'my';
  2015. else $menuType = $type == 'custom' ? 'team' : $type;
  2016. if(isset($this->lang->doc->menu->{$menuType})) $this->lang->doc->menu->{$menuType}['alias'] .= ',' . $this->app->rawMethod;
  2017. $docVersion = 0;
  2018. $isApi = is_string($docID) && strpos($docID, 'api.') === 0;
  2019. if($isApi) $docID = str_replace('api.', '', $docID);
  2020. if(is_string($docID) && strpos($docID, '_') !== false) list($docID, $docVersion) = explode('_', $docID);
  2021. $this->view->type = $type;
  2022. $this->view->spaceID = $spaceID;
  2023. $this->view->libID = $libID;
  2024. $this->view->moduleID = $moduleID;
  2025. $this->view->docID = $isApi ? "api.$docID" : (int)$docID;
  2026. $this->view->docVersion = (int)$docVersion;
  2027. $this->view->mode = $mode;
  2028. $this->view->filterType = $filterType;
  2029. $this->view->search = $search;
  2030. $this->view->recTotal = $recTotal;
  2031. $this->view->recPerPage = $recPerPage;
  2032. $this->view->pageID = $pageID;
  2033. $this->view->orderBy = $orderBy;
  2034. $this->view->objectType = $type;
  2035. $this->view->noSpace = $noSpace;
  2036. $this->view->objectID = $spaceID;
  2037. $this->view->users = $this->dao->select('account,realname,avatar')->from(TABLE_USER)->where('deleted')->eq('0')->fetchAll('account');
  2038. $this->view->title = isset($this->lang->doc->spaceList[$type]) ? $this->lang->doc->spaceList[$type] : $this->lang->doc->common;
  2039. $this->display();
  2040. }
  2041. /**
  2042. * Doc quick access page.
  2043. * 快捷访问页面。
  2044. *
  2045. * @param string $type 'view'|'collect'|'createdby'|'editedby'
  2046. * @param int $docID
  2047. * @param string $orderBy
  2048. * @param int $recPerPage
  2049. * @param int $pageID
  2050. * @access public
  2051. * @return void
  2052. */
  2053. public function quick($type = 'view', $docID = 0, $orderBy = '', $recPerPage = 20, $pageID = 1)
  2054. {
  2055. if(empty($orderBy)) $orderBy = 'id_desc';
  2056. if(!isset($this->config->doc->quickMenu[$type])) $type = 'view';
  2057. $menu = $this->config->doc->quickMenu[$type];
  2058. $currentUser = $this->app->user->account;
  2059. $docs = $this->doc->getMineList($type, 'all', 0, $orderBy);
  2060. $order = 0;
  2061. foreach($docs as $doc)
  2062. {
  2063. $order++;
  2064. unset($doc->draft);
  2065. $doc->originLIb = $doc->lib;
  2066. $doc->lib = $menu['id'];
  2067. $doc->order = $order;
  2068. $doc->isCollector = strpos($doc->collector, ',' . $currentUser . ',') !== false;
  2069. }
  2070. $this->view->docs = $docs;
  2071. $this->view->menu = $menu;
  2072. $this->view->type = $type;
  2073. $this->view->docID = $docID;
  2074. $this->view->orderBy = $orderBy;
  2075. $this->view->recPerPage = $recPerPage;
  2076. $this->view->pageID = $pageID;
  2077. $this->view->users = $this->dao->select('account,realname,avatar')->from(TABLE_USER)->where('deleted')->eq('0')->fetchAll('account');
  2078. $this->view->title = $this->lang->doc->quick;
  2079. $this->display();
  2080. }
  2081. /**
  2082. * Ajax: Get doc space data.
  2083. * Ajax: 获取文档空间数据。
  2084. *
  2085. * @param string $type
  2086. * @param int $space
  2087. * @access public
  2088. * @return void
  2089. * @param int $spaceID
  2090. * @param string $picks
  2091. * @param int $libID
  2092. */
  2093. public function ajaxGetSpaceData($type = 'custom', $spaceID = 0, $picks = '', $libID = 0)
  2094. {
  2095. $this->doc->setMenuByType($type, (int)$spaceID, 0);
  2096. if($type === 'template')
  2097. {
  2098. $modules = $this->doc->getTemplateModules();
  2099. $moduleNames = array_column($modules, 'fullName', 'id');
  2100. $templateList = $this->doc->getDocTemplateList(0, 'all');
  2101. $templateList = $this->doc->filterDeletedDocs($templateList);
  2102. $templateList = $this->doc->filterPrivDocs($templateList, 'template');
  2103. foreach($templateList as $template)
  2104. {
  2105. $template->moduleName = zget($moduleNames, $template->module);
  2106. }
  2107. $data = array('spaceID' => $spaceID, 'docs' => array_values($templateList));
  2108. $data['spaces'][] = array('name' => $this->lang->doc->template, 'id' => $spaceID);
  2109. $data['modules'] = $modules;
  2110. $scopeList = $this->doc->getTemplateScopes();
  2111. foreach($scopeList as $scope) $data['libs'][] = array('id' => $scope->id, 'name' => $scope->name, 'space' => $spaceID);
  2112. }
  2113. else
  2114. {
  2115. $noPicks = empty($picks);
  2116. $picks = $noPicks ? '' : ",$picks,";
  2117. list($spaces, $spaceID) = $this->doc->getSpaces($type, $spaceID);
  2118. $data = array('spaceID' => (int)$spaceID);
  2119. $libs = $this->doc->getLibsOfSpace($type, $spaceID);
  2120. $libIds = array_keys($libs);
  2121. foreach($libs as $lib) $lib->order = (int)$lib->order;
  2122. if($noPicks || strpos($picks, ',space,') !== false) $data['spaces'] = $spaces;
  2123. if($noPicks || strpos($picks, ',lib,') !== false) $data['libs'] = array_values($libs);
  2124. if($noPicks || strpos($picks, ',module,') !== false) $data['modules'] = array_values($this->doc->getModulesOfLibs($libIds));
  2125. if($noPicks || strpos($picks, ',doc,') !== false) $data['docs'] = array_values($this->doc->getDocsOfLibs($libIds + array($spaceID), $type));
  2126. }
  2127. $this->send($data);
  2128. }
  2129. /**
  2130. * Ajax: Get doc data.
  2131. * Ajax: 获取文档数据。
  2132. *
  2133. * @param string|int $docID
  2134. * @param int $version
  2135. * @access public
  2136. * @return void
  2137. */
  2138. public function ajaxGetDoc($docID, $version = 0, $details = 'no')
  2139. {
  2140. if(is_string($docID) && strpos($docID, 'api.') === 0)
  2141. {
  2142. $apiID = (int)str_replace('api.', '', $docID);
  2143. echo $this->fetch('api', 'ajaxGetApi', "apiID=$apiID&version=$version");
  2144. return;
  2145. }
  2146. $docID = (int)$docID;
  2147. $doc = $this->doc->getByID($docID, $version);
  2148. $doc->lib = (int)$doc->lib;
  2149. $doc->module = (int)$doc->module;
  2150. $doc->privs = array('edit' => common::hasPriv('doc', 'edit', $doc) && $doc->acl == 'open');
  2151. $doc->editors = $this->doc->getEditors($docID);
  2152. $doc->draft = $doc->status == 'draft' ? $this->doc->getContent($docID, 0) : null;
  2153. $lib = $this->doc->getLibByID((int)$doc->lib);
  2154. $objectType = $lib->type;
  2155. if(empty($objectType))
  2156. {
  2157. if($lib->execution) $objectType = 'execution';
  2158. elseif($lib->project) $objectType = 'project';
  2159. elseif($lib->product) $objectType = 'product';
  2160. }
  2161. $this->doc->setDocPriv($doc, $objectType);
  2162. if($details == 'yes')
  2163. {
  2164. $objectID = $this->doc->getObjectIDByLib($lib, $objectType);
  2165. $object = in_array($objectType, array('product', 'project', 'execution')) ? $this->doc->getObjectByID($objectType, $objectID) : $this->doc->getLibByID((int)$objectID);
  2166. $doc->libInfo = $lib;
  2167. $doc->objectType = $objectType;
  2168. $doc->object = $object;
  2169. }
  2170. if(!empty($doc->rawContent))
  2171. {
  2172. $doc->html = $doc->content;
  2173. $doc->content = $doc->rawContent;
  2174. unset($doc->rawContent);
  2175. if(empty($doc->templateType) && $doc->contentType == 'doc' && preg_match('/ src="{([0-9]+)(\.(\w+))?}" /', $doc->html))
  2176. {
  2177. $doc->contentType = 'html';
  2178. $doc->content = preg_replace('/ src="{([0-9]+)(\.(\w+))?}" /', ' src="' . helper::createLink('file', 'read', "fileID=$1", "$3") . '" ', $doc->html);
  2179. }
  2180. }
  2181. if($docID) $this->doc->createAction($docID, 'view');
  2182. $this->send($doc);
  2183. }
  2184. /**
  2185. * Get files by type and objectID.
  2186. * 根据类型和对象ID获取文件列表。
  2187. *
  2188. * @param string $type
  2189. * @param int $objectID
  2190. * @param string $browseType
  2191. * @param string $orderBy
  2192. * @param int $recTotal
  2193. * @param int $recPerPage
  2194. * @param int $pageID
  2195. * @access public
  2196. * @return void
  2197. */
  2198. public function ajaxGetFiles($type, $objectID, $browseType = '', $orderBy = 'id_desc', $recTotal = 0, $recPerPage = 9999, $pageID = 1)
  2199. {
  2200. if(common::hasPriv('doc', 'showFiles'))
  2201. {
  2202. /* Load pager. */
  2203. $rawMethod = $this->app->rawMethod;
  2204. $this->app->rawMethod = 'showFiles';
  2205. $this->app->loadClass('pager', true);
  2206. $pager = new pager($recTotal, $recPerPage, $pageID);
  2207. $this->app->rawMethod = $rawMethod;
  2208. $files = $this->doc->getLibFiles($type, $objectID, $browseType, 0, $orderBy, $pager);
  2209. $sourcePairs = $this->doc->getFileSourcePairs($files);
  2210. $files = $this->docZen->processFiles($files, array(), $sourcePairs, true);
  2211. echo json_encode(array_values($files)); // $this->send($files); not work.
  2212. }
  2213. else
  2214. {
  2215. echo '[]';
  2216. }
  2217. }
  2218. /**
  2219. * Get lib summaries by space type and space list.
  2220. *
  2221. * @param string $spaceType
  2222. * @param string $spaceList
  2223. * @access public
  2224. * @return void
  2225. */
  2226. public function ajaxGetLibSummaries($spaceType, $spaceList)
  2227. {
  2228. $libsMap = $this->doc->getLibsOfSpaces($spaceType, $spaceList, 0);
  2229. echo json_encode($libsMap);
  2230. }
  2231. /**
  2232. * Ajax modal for setting doc basic info.
  2233. * 设置文档基本信息的模态框。
  2234. *
  2235. * @param string $objectType
  2236. * @param int $objectID
  2237. * @param int $libID
  2238. * @param int $moduleID
  2239. * @param int $docID
  2240. * @param string $isDraft
  2241. * @access public
  2242. * @param int $parentID
  2243. * @param string $modalType
  2244. */
  2245. public function setDocBasic($objectType, $objectID, $libID = 0, $moduleID = 0, $parentID = 0, $docID = 0, $isDraft = 'no', $modalType = 'doc')
  2246. {
  2247. $this->doc->setMenuByType($objectType, (int)$objectID, (int)$libID);
  2248. $lib = $libID ? $this->doc->getLibByID($libID) : '';
  2249. $isCreate = empty($docID);
  2250. if($docID) $doc = $this->doc->getByID($docID);
  2251. $title = $this->lang->settings;
  2252. if($modalType == 'doc')
  2253. {
  2254. $title = $parentID ? $this->lang->doc->addSubDoc : $this->lang->doc->create;
  2255. if($objectType == 'template') $title = $parentID ? $this->lang->docTemplate->addSubDocTemplate : $this->lang->docTemplate->create;
  2256. if($isDraft == 'no') $title = $this->lang->settings;
  2257. }
  2258. if($modalType == 'chapter') $title = $isCreate ? $this->lang->doc->addChapter : $this->lang->doc->editChapter;
  2259. if($isCreate)
  2260. {
  2261. if(!$moduleID && $docID)
  2262. {
  2263. $parentDoc = $this->doc->getByID($parentID);
  2264. $moduleID = $parentDoc->module;
  2265. }
  2266. if(empty($objectID) && $lib) $objectID = $this->doc->getObjectIDByLib($lib);
  2267. if($lib && $objectType != 'template') $objectType = $lib->type;
  2268. $unclosed = strpos($this->config->doc->custom->showLibs, 'unclosed') !== false ? 'unclosedProject' : '';
  2269. $libPairs = $this->doc->getLibs($objectType, "{$unclosed}", $libID, $objectID);
  2270. $moduleID = $moduleID ? (int)$moduleID : (int)$this->cookie->lastDocModule;
  2271. if(!$libID && !empty($libPairs)) $libID = key($libPairs);
  2272. if(empty($lib) && $libID) $lib = $this->doc->getLibByID($libID);
  2273. if($objectType == 'custom' || $objectType == 'mine') $this->view->spaces = $this->doc->getSubSpacesByType($objectType, true);
  2274. $this->docZen->setObjectsForCreate($objectType, empty($lib) ? null : $lib, $unclosed, $objectID);
  2275. $this->view->optionMenu = empty($libID) ? array() : $this->loadModel('tree')->getOptionMenu($libID, 'doc', 0);
  2276. }
  2277. else
  2278. {
  2279. $parentID = (int)$doc->parent;
  2280. $moduleID = (int)$doc->module;
  2281. $libID = (int)$doc->lib;
  2282. $lib = $this->doc->getLibByID($libID);
  2283. if($lib && $objectType != 'template') $objectType = $lib->type;
  2284. $objectID = $this->doc->getObjectIDByLib($lib);
  2285. $libPairs = $this->doc->getLibs($objectType, '', $libID, $objectID);
  2286. if($objectType == 'custom' || $objectType == 'mine') $this->view->spaces = $this->doc->getSubSpacesByType($objectType, true);
  2287. $this->docZen->setObjectsForEdit($objectType, $objectID);
  2288. $this->view->doc = $doc;
  2289. $this->view->optionMenu = $this->loadModel('tree')->getOptionMenu($libID, 'doc', 0);
  2290. }
  2291. $chapterAndDocs = $this->doc->getDocsOfLibs(array($libID), $objectType, $docID, $objectType == 'template' ? true : false);
  2292. if($objectType == 'template' && !empty($moduleID)) $chapterAndDocs = array_filter($chapterAndDocs, function ($docInfo) use ($moduleID) {
  2293. return $docInfo->module == $moduleID;
  2294. });
  2295. if(isset($doc) && !empty($doc->parent) && !isset($chapterAndDocs[$doc->parent])) $chapterAndDocs[$doc->parent] = $this->doc->fetchByID($doc->parent);
  2296. $modulePairs = empty($libID) || $modalType == 'chapter' || $objectType == 'template' ? array() : $this->loadModel('tree')->getOptionMenu($libID, 'doc', 0);
  2297. if($objectType == 'template' && !empty($parentID))
  2298. {
  2299. $parentDoc = $this->doc->fetchByID($parentID);
  2300. $parentPath = trim($parentDoc->path, ',') . ",";
  2301. $topTemplate = substr($parentPath, 0, strpos($parentPath, ',')) ?: $parentID;
  2302. foreach($chapterAndDocs as $key => $template)
  2303. {
  2304. if(strpos(",{$template->path},", ",{$topTemplate},") === false) unset($chapterAndDocs[$key]);
  2305. }
  2306. }
  2307. $this->view->chapterAndDocs = $this->doc->buildNestedDocs($chapterAndDocs, $modulePairs);
  2308. if($objectType == 'template')
  2309. {
  2310. $scopeList = $this->doc->getTemplateScopes();
  2311. $this->view->scopeItems = $this->doc->getScopeItems($scopeList);
  2312. }
  2313. else
  2314. {
  2315. $this->view->users = $this->user->getPairs('nocode|noclosed|nodeleted');
  2316. $this->view->groups = $this->loadModel('group')->getPairs();
  2317. }
  2318. $docTitle = '';
  2319. if(!empty($doc))
  2320. {
  2321. $docTitle = $doc->title;
  2322. }
  2323. elseif($this->post->title)
  2324. {
  2325. $docTitle = $this->post->title;
  2326. }
  2327. $this->view->docID = $docID;
  2328. $this->view->docTitle = $docTitle;
  2329. $this->view->mode = empty($docID) ? 'create' : 'edit';
  2330. $this->view->libID = $libID;
  2331. $this->view->moduleID = $moduleID;
  2332. $this->view->objectID = $objectID;
  2333. $this->view->objectType = $objectType;
  2334. $this->view->lib = $lib;
  2335. $this->view->libs = $libPairs;
  2336. $this->view->parentID = $parentID;
  2337. $this->view->isDraft = $isDraft == 'yes';
  2338. $this->view->title = $title;
  2339. $this->view->modalType = $modalType;
  2340. $this->view->isCreate = $isCreate;
  2341. $this->display();
  2342. }
  2343. /**
  2344. * AJAX: 通过文档ID获取Confluence子文档。
  2345. * AJAX: Get confluence subdocuments by doc ID.
  2346. *
  2347. * @param int $originPageID 当前Confluence文档ID
  2348. * @param string $title 选择的父页面标题
  2349. * @param int $level 展示层级
  2350. * @access public
  2351. * @return void
  2352. */
  2353. public function ajaxGetConfluenceChildren($originPageID, $title, $level = PHP_INT_MAX)
  2354. {
  2355. $parentID = $this->doc->getDocIdByTitle($originPageID, $title);
  2356. if(dao::isError()) return $this->send(array('result' => 'fail', 'message' => dao::getError()));
  2357. $docs = $this->docZen->getDocChildrenByRecursion((int)$parentID, $level);
  2358. if(dao::isError()) return $this->send(array('result' => 'fail', 'message' => dao::getError()));
  2359. return $this->send(array('result' => 'success', 'data' => $docs));
  2360. }
  2361. /**
  2362. * Ajax: Retrieve corresponding user information in the Zen path through Confluence user ID.
  2363. * Ajax: 通过Confluence用户ID获取在禅道中的对应用户信息。
  2364. *
  2365. * @param string $username
  2366. * @access public
  2367. * @return void
  2368. */
  2369. public function ajaxGetConfluenceUser($username)
  2370. {
  2371. $user = $this->doc->getUserByConfluenceUserID($username);
  2372. return $this->send(array('result' => 'success', 'data'=> $user));
  2373. }
  2374. /**
  2375. * Manage scope.
  2376. * 维护范围。
  2377. *
  2378. * @access public
  2379. * @return void
  2380. */
  2381. public function manageScope()
  2382. {
  2383. $scopeList = $this->doc->getTemplateScopes();
  2384. if(!empty($_POST))
  2385. {
  2386. $scopes = $this->post->scopes;
  2387. $oldScopes = $newScopes = array();
  2388. foreach($scopes as $index => $name)
  2389. {
  2390. if(empty(trim($name))) continue;
  2391. $scopeID = $_POST['id'][$index];
  2392. if($scopeID)
  2393. {
  2394. $oldScopes[$scopeID] = $name;
  2395. }
  2396. else
  2397. {
  2398. $newScopes[$index] = $name;
  2399. }
  2400. }
  2401. $deletedScopes = array_diff(array_keys($scopeList), array_keys($oldScopes));
  2402. if(!empty($deletedScopes)) $this->doc->deleteTemplateScopes($deletedScopes);
  2403. if(dao::isError()) return $this->sendError(array('message' => dao::getError()));
  2404. if(!empty($oldScopes)) $this->doc->updateTemplateScopes($oldScopes);
  2405. if(dao::isError()) return $this->sendError(array('message' => dao::getError()));
  2406. if(!empty($newScopes)) $this->doc->insertTemplateScopes($newScopes);
  2407. if(dao::isError()) return $this->sendError(array('message' => dao::getError()));
  2408. return $this->sendSuccess(array('closeModal' => true, 'load' => true));
  2409. }
  2410. $this->view->scopeList = $scopeList;
  2411. $this->display();
  2412. }
  2413. /**
  2414. * AJAX: Judge can be deleted scope.
  2415. * AJAX: 判断范围是否可以被删除。
  2416. *
  2417. * @param int $scopeID
  2418. * @access public
  2419. * @return array
  2420. */
  2421. public function ajaxJudgeCanBeDeleted($scopeID = 0)
  2422. {
  2423. if(empty($scopeID)) return $this->sendSuccess(array('message' => 'success'));
  2424. $templates = $this->doc->getScopeTemplates(array($scopeID));
  2425. if(!empty($templates[$scopeID])) return $this->sendError($this->lang->docTemplate->scopeHasTemplateTips);
  2426. $modules = $this->doc->getTemplateModules($scopeID);
  2427. if(!empty($modules)) return $this->sendError($this->lang->docTemplate->scopeHasModuleTips);
  2428. return $this->sendSuccess(array('message' => 'success'));
  2429. }
  2430. }