2734 lines
110 KiB
PHP
Executable file
2734 lines
110 KiB
PHP
Executable file
<?php
|
||
declare(strict_types=1);
|
||
/**
|
||
* The control file of doc module of ZenTaoPMS.
|
||
*
|
||
* @copyright Copyright 2009-2023 禅道软件(青岛)有限公司(ZenTao Software (Qingdao) Co., Ltd. www.cnezsoft.com)
|
||
* @license ZPL(http://zpl.pub/page/zplv12.html) or AGPL(https://www.gnu.org/licenses/agpl-3.0.en.html)
|
||
* @author Chunsheng Wang <chunsheng@cnezsoft.com>
|
||
* @package doc
|
||
* @version $Id: control.php 933 2010-07-06 06:53:40Z wwccss $
|
||
* @link https://www.zentao.net
|
||
*/
|
||
class doc extends control
|
||
{
|
||
public docModel $doc;
|
||
|
||
/**
|
||
* 构造函数,加载通用模块。
|
||
* Construct function, load user, tree, action auto.
|
||
*
|
||
* @access public
|
||
* @return void
|
||
*/
|
||
public function __construct($moduleName = '', $methodName = '')
|
||
{
|
||
parent::__construct($moduleName, $methodName);
|
||
$this->loadModel('user');
|
||
$this->loadModel('tree');
|
||
$this->loadModel('action');
|
||
$this->loadModel('product');
|
||
$this->loadModel('project');
|
||
$this->loadModel('execution');
|
||
}
|
||
|
||
/**
|
||
* 最近访问的空间首页。
|
||
* Last viewed doc space home.
|
||
*
|
||
* @access public
|
||
* @return void
|
||
*/
|
||
public function lastViewedSpaceHome()
|
||
{
|
||
$lastViewedSpaceHome = $this->doc->getLastViewed('lastViewedSpaceHome');
|
||
if($this->config->vision == 'lite' && $lastViewedSpaceHome == 'api') $lastViewedSpaceHome = 'mine';
|
||
|
||
if($lastViewedSpaceHome === 'api') return $this->locate($this->createLink('api', 'index'));
|
||
|
||
$spaceMap = array(
|
||
'mine' => 'mySpace',
|
||
'product' => 'productSpace',
|
||
'project' => 'projectSpace',
|
||
'custom' => 'teamSpace'
|
||
);
|
||
$method = $spaceMap[$lastViewedSpaceHome];
|
||
if(empty($method)) return $this->locate($this->createLink('doc', 'mySpace'));
|
||
|
||
return $this->locate($this->createLink('doc', $method));
|
||
}
|
||
|
||
/**
|
||
* 最近访问的空间。
|
||
* Last viewed doc space.
|
||
*
|
||
* @access public
|
||
* @return void
|
||
*/
|
||
public function lastViewedSpace()
|
||
{
|
||
$lastViewedSpaceHome = $this->doc->getLastViewed('lastViewedSpaceHome');
|
||
if($this->config->vision == 'lite' && $lastViewedSpaceHome == 'api') $lastViewedSpaceHome = 'mine';
|
||
|
||
if($lastViewedSpaceHome === 'api') return $this->locate($this->createLink('api', 'index'));
|
||
|
||
$spaceMap = array(
|
||
'mine' => 'mySpace',
|
||
'product' => 'productSpace',
|
||
'project' => 'projectSpace',
|
||
'custom' => 'teamSpace'
|
||
);
|
||
$method = $spaceMap[$lastViewedSpaceHome];
|
||
if(empty($method) || !common::hasPriv('doc', $method)) return $this->locate($this->createLink('doc', 'mySpace'));
|
||
|
||
$lastViewedSpace = $this->doc->getLastViewed('lastViewedSpace');
|
||
if(!is_numeric($lastViewedSpace)) return $this->locate($this->createLink('doc', 'mySpace'));
|
||
return $this->locate($this->createLink('doc', $method, "objectID={$lastViewedSpace}"));
|
||
}
|
||
|
||
/**
|
||
* 最近访问的库。
|
||
* Last viewed doc lib.
|
||
*
|
||
* @access public
|
||
* @return void
|
||
*/
|
||
public function lastViewedLib()
|
||
{
|
||
$lastViewedSpaceHome = $this->doc->getLastViewed('lastViewedSpaceHome');
|
||
$lastViewedLib = $this->doc->getLastViewed('lastViewedLib');
|
||
|
||
if($lastViewedSpaceHome === 'api')
|
||
{
|
||
if(is_numeric($lastViewedLib)) return $this->locate($this->createLink('api', 'index', "libID={$lastViewedLib}"));
|
||
return $this->locate($this->createLink('api', 'index'));
|
||
}
|
||
|
||
$lastViewedSpace = $this->doc->getLastViewed('lastViewedSpace');
|
||
$spaceMap = array(
|
||
'mine' => 'mySpace',
|
||
'product' => 'productSpace',
|
||
'project' => 'projectSpace',
|
||
'custom' => 'teamSpace'
|
||
);
|
||
$method = $spaceMap[$lastViewedSpaceHome];
|
||
if(empty($method)) return $this->locate($this->createLink('doc', 'mySpace'));
|
||
|
||
if(!is_numeric($lastViewedSpace) || !is_numeric($lastViewedLib)) return $this->locate($this->createLink('doc', 'mySpace'));
|
||
return $this->locate($this->createLink('doc', $method, "objectID={$lastViewedSpace}&libID={$lastViewedLib}"));
|
||
}
|
||
|
||
/**
|
||
* 设置上次访问的文档对象。
|
||
* Set last viewed doc object.
|
||
*
|
||
* @access public
|
||
* @return void
|
||
*/
|
||
public function ajaxSetLastViewed()
|
||
{
|
||
if(empty($_POST)) return $this->send(array('result' => 'fail'));
|
||
$this->doc->setLastViewed($_POST);
|
||
return $this->send(array('result' => 'success'));
|
||
}
|
||
|
||
/**
|
||
* 文档仪表盘。
|
||
* Document dashboard.
|
||
*
|
||
* @access public
|
||
* @return void
|
||
*/
|
||
public function index()
|
||
{
|
||
$this->session->set('docList', $this->app->getURI(true), 'doc');
|
||
echo $this->fetch('block', 'dashboard', 'dashboard=doc');
|
||
}
|
||
|
||
/**
|
||
* 禅道数据列表。
|
||
* Zentao data list.
|
||
*
|
||
* @param string $type
|
||
* @param int|string $blockID
|
||
* @access public
|
||
* @return void
|
||
*/
|
||
public function zentaoList(string $type, int|string $blockID)
|
||
{
|
||
if(is_string($blockID)) $blockID = (int)str_replace('__TML_ZENTAOLIST__', '', $blockID);
|
||
|
||
$blockData = $this->doc->getZentaoList($blockID);
|
||
if(!$blockData)
|
||
{
|
||
if(helper::isAjaxRequest('fetch'))
|
||
{
|
||
echo '<div class="text-gray text-sm surface p-1">' . $this->lang->notFound . '</div>';
|
||
return;
|
||
}
|
||
return $this->sendError($this->lang->notFound);
|
||
}
|
||
|
||
$doc = $this->doc->getByID($blockData->doc);
|
||
$this->view->isTemplate = !empty($doc->templateType) && !in_array($blockData->extra, array('fromReview', 'fromReport'));
|
||
$this->view->fromReport = $blockData->extra == 'fromReport';
|
||
|
||
$noSupport = false;
|
||
if($this->view->fromReport)
|
||
{
|
||
$project = $this->loadModel('project')->fetchByID((int)$doc->project);
|
||
$noSupport = in_array($type, array('HLDS', 'DDS', 'DBDS', 'ADS')) && in_array($project->model, array('scrum', 'agileplus', 'kanban'));
|
||
}
|
||
$this->view->noSupport = $noSupport;
|
||
|
||
if($this->view->isTemplate)
|
||
{
|
||
$this->view->title = sprintf($this->lang->doc->insertTitle, $this->lang->docTemplate->zentaoList[$type]);
|
||
$this->view->type = $type;
|
||
$this->view->blockID = $blockID;
|
||
$this->view->settings = $blockData->settings;
|
||
$this->view->searchTab = zget($blockData->content, 'searchTab', '');
|
||
|
||
if($type == 'productCase' || $type == 'projectCase') $this->view->caseStage = $blockData->content->caseStage;
|
||
|
||
return $this->display();
|
||
}
|
||
|
||
$fromTemplate = in_array($blockData->extra, array('fromTemplate', 'fromReview', 'fromReport'));
|
||
if($fromTemplate)
|
||
{
|
||
$this->view->title = sprintf($this->lang->doc->insertTitle, $this->lang->docTemplate->zentaoList[$type]);
|
||
$this->view->searchTab = zget($blockData->content, 'searchTab', '');
|
||
$this->view->isSetted = isset($blockData->content->data) && isset($blockData->content->cols) || isset($blockData->content->ganttOptions);
|
||
if($type == 'productCase' || $type == 'projectCase') $this->view->caseStage = $blockData->content->caseStage;
|
||
}
|
||
else
|
||
{
|
||
$this->view->title = sprintf($this->lang->doc->insertTitle, $this->lang->doc->zentaoList[$type]);
|
||
}
|
||
|
||
if($type == 'gantt')
|
||
{
|
||
$this->view->ganttData = (array)zget($blockData->content, 'ganttOptions', array());
|
||
$this->view->ganttFields = (array)zget($blockData->content, 'ganttFields', array());
|
||
$this->view->showFields = zget($blockData->content, 'showFields', '');
|
||
}
|
||
else
|
||
{
|
||
$data = (array)zget($blockData->content, 'data', array());
|
||
if($type == 'task')
|
||
{
|
||
foreach($data as $task) $task->canView = $this->execution->checkPriv($task->execution);
|
||
}
|
||
|
||
$this->app->loadClass('pager', true);
|
||
|
||
$this->view->idList = (array)zget($blockData->content, 'idList', array());
|
||
$this->view->cols = (array)zget($blockData->content, 'cols', array());
|
||
$this->view->data = $data;
|
||
$this->view->pager = new pager(count($data), 10);
|
||
}
|
||
|
||
$this->view->type = $type;
|
||
$this->view->settings = $blockData->settings;
|
||
$this->view->users = $this->loadModel('user')->getPairs('noletter|pofirst');
|
||
$this->view->blockID = $blockID;
|
||
$this->view->fromTemplate = $fromTemplate;
|
||
|
||
if(strpos(',productStory,ER,UR,planStory,projectStory', $type) !== false) $this->docZen->assignStoryGradeData($type);
|
||
|
||
if($type == 'productRelease')
|
||
{
|
||
$releaseList = array();
|
||
foreach($this->view->data as $release)
|
||
{
|
||
if($release->id == $release->rowID) $releaseList[$release->id] = $release;
|
||
}
|
||
$children = implode(',', array_column($releaseList, 'releases'));
|
||
$childReleases = $this->loadModel('release')->getListByCondition(explode(',', $children), 0, true);
|
||
$this->view->data = $this->release->processReleaseListData($releaseList, $childReleases, false);
|
||
}
|
||
|
||
$this->display();
|
||
}
|
||
|
||
/**
|
||
* 导出禅道数据列表。
|
||
* Export Zentao data list.
|
||
*
|
||
* @param int|string $blockID
|
||
* @access public
|
||
* @return void
|
||
*/
|
||
public function ajaxExportZentaoList(int|string $blockID)
|
||
{
|
||
if(is_string($blockID)) $blockID = (int)str_replace('__TML_ZENTAOLIST__', '', $blockID);
|
||
|
||
$blockData = $this->doc->getZentaoList($blockID);
|
||
if(!$blockData) return $this->lang->notFound;
|
||
|
||
if(!helper::isAjaxRequest('fetch')) return $this->locate(inlink('zentaoList', "type={$blockData->type}&blockID={$blockID}"));
|
||
|
||
if(empty($blockData->title))
|
||
{
|
||
$blockType = $blockData->type;
|
||
$blockContent = $blockData->content;
|
||
$templateLang = zget($this->lang, 'docTemplate', array());
|
||
$searchTab = zget($blockContent, 'searchTab', '');
|
||
|
||
$blockTitle = '';
|
||
if(!empty($templateLang))
|
||
{
|
||
$blockTitle = empty($templateLang->searchTabList[$blockType][$searchTab]) ? '' : $templateLang->searchTabList[$blockType][$searchTab] . $templateLang->of;
|
||
if($blockType == 'bug' && $searchTab == 'overduebugs') $blockTitle = $templateLang->overdue . $templateLang->of;
|
||
if(!empty($blockContent->caseStage)) $blockTitle .= $this->app->loadLang('testcase')->testcase->stageList[$blockContent->caseStage];
|
||
}
|
||
|
||
$blockData->title = $blockTitle . zget($this->lang->doc->zentaoList, $blockType, '') . $this->lang->doc->list;
|
||
}
|
||
$content = $this->docZen->exportZentaoList($blockData);
|
||
echo $content;
|
||
}
|
||
|
||
/**
|
||
* 构建禅道数据列表。
|
||
* Build Zentao data list.
|
||
*
|
||
* @param int $docID
|
||
* @param string $type
|
||
* @param int $oldBlockID
|
||
* @access public
|
||
* @return void
|
||
*/
|
||
public function buildZentaoList(int $docID, string $type, int $oldBlockID = 0)
|
||
{
|
||
$docblock = new stdClass();
|
||
$docblock->doc = $docID;
|
||
$docblock->type = $type;
|
||
$docblock->settings = $this->post->url;
|
||
if($type == 'gantt')
|
||
{
|
||
$docblock->content = json_encode(array('ganttOptions' => json_decode($this->post->ganttOptions), 'showFields' => $this->post->showFields, 'ganttFields' => json_decode($this->post->ganttFields)));
|
||
}
|
||
else
|
||
{
|
||
$docblock->content = json_encode(array('cols' => json_decode($this->post->cols), 'data' => json_decode($this->post->data), 'idList' => $this->post->idList));
|
||
}
|
||
|
||
$this->dao->insert(TABLE_DOCBLOCK)->data($docblock)->exec();
|
||
if(dao::isError()) return print(json_encode(array('result' => 'fail', 'message' => dao::getError())));
|
||
|
||
$newBlockID = $this->dao->lastInsertId();
|
||
|
||
return print(json_encode(array('result' => 'success', 'oldBlockID' => $oldBlockID, 'newBlockID' => $newBlockID)));
|
||
}
|
||
|
||
/**
|
||
* 我的空间。
|
||
* My space.
|
||
*
|
||
* @param int $objectID
|
||
* @param int $libID
|
||
* @param int $moduleID
|
||
* @param string $browseType all|draft|bysearch
|
||
* @param int $param
|
||
* @param string $orderBy
|
||
* @param int $recTotal
|
||
* @param int $recPerPage
|
||
* @param int $pageID
|
||
* @access public
|
||
* @return void
|
||
*/
|
||
public function mySpace(int $objectID = 0, int $libID = 0, int $moduleID = 0, string $browseType = 'all', int $param = 0, string $orderBy = 'order_asc', int $recTotal = 0, int $recPerPage = 20, int $pageID = 1, string $mode = '', int $docID = 0, string $search = '')
|
||
{
|
||
$this->docZen->initLibForMySpace();
|
||
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");
|
||
}
|
||
|
||
/**
|
||
* 创建一个空间。
|
||
* Create a space.
|
||
*
|
||
* @param string $type
|
||
* @access public
|
||
* @return void
|
||
*/
|
||
public function createSpace(string $type = '')
|
||
{
|
||
if(!empty($_POST))
|
||
{
|
||
$this->lang->doc->name = $this->lang->doclib->spaceName;
|
||
$space = form::data()->setDefault('addedBy', $this->app->user->account)->get();
|
||
if($type) $space->type = $type;
|
||
|
||
$spaceID = $this->doc->doInsertLib($space);
|
||
if(dao::isError()) return $this->send(array('result' => 'fail', 'message' => dao::getError()));
|
||
|
||
$this->loadModel('action')->create('docspace', $spaceID, 'created');
|
||
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))));
|
||
}
|
||
|
||
$this->display();
|
||
}
|
||
|
||
/**
|
||
* 创建一个文档库。
|
||
* Create a library.
|
||
*
|
||
* @param string $type api|project|product|execution|custom|mine
|
||
* @param int $objectID
|
||
* @param int $libID
|
||
* @access public
|
||
* @return void
|
||
*/
|
||
public function createLib(string $type = '', int $objectID = 0, int $libID = 0)
|
||
{
|
||
$this->app->loadLang('api');
|
||
|
||
/* 项目模板下setMenu会修改common语言项,所以执行文档要先执行setAclForCreateLib。 */
|
||
if($type != 'project') $this->docZen->setAclForCreateLib($type);
|
||
$this->doc->setMenuByType($type, (int)$objectID, (int)$libID);
|
||
if($type == 'project') $this->docZen->setAclForCreateLib($type);
|
||
|
||
if(!empty($_POST))
|
||
{
|
||
$lib = $this->docZen->buildLibForCreateLib();
|
||
if(dao::isError()) return $this->send(array('result' => 'fail', 'message' => dao::getError()));
|
||
|
||
$libID = $this->doc->createLib($lib, (string)$this->post->type, (string)$this->post->libType);
|
||
if(dao::isError()) return $this->send(array('result' => 'fail', 'message' => dao::getError()));
|
||
|
||
if($type == 'custom' || $type == 'mine')
|
||
{
|
||
$lib = $this->doc->getLibByID($libID);
|
||
$objectID = $lib->parent;
|
||
}
|
||
|
||
return $this->docZen->responseAfterCreateLib($type, $objectID, $libID, $lib->name, $lib->orderBy);
|
||
}
|
||
|
||
$objects = array();
|
||
if($type == 'project')
|
||
{
|
||
$this->view->project = $this->project->getById($objectID);
|
||
if($this->app->tab == 'doc') $this->view->executionPairs = $this->execution->getPairs($objectID, 'all', 'multiple,leaf,noprefix');
|
||
}
|
||
|
||
if($type == 'execution')
|
||
{
|
||
$objects = $this->execution->getPairs(0, 'all', 'multiple,leaf,noprefix,withobject');
|
||
$execution = $this->execution->getByID($objectID);
|
||
if($execution->type == 'stage') $this->lang->doc->execution = str_replace($this->lang->executionCommon, $this->lang->project->stage, $this->lang->doc->execution);
|
||
$this->view->execution = $this->doc->fetchByID($objectID, 'execution');
|
||
}
|
||
|
||
if($type == 'custom' || $type == 'mine' || $type == 'doctemplate')
|
||
{
|
||
$lib = $this->doc->getLibByID($libID);
|
||
$this->view->spaces = $this->doc->getSubSpacesByType($type);
|
||
$this->view->spaceID = !empty($lib->parent) ? $lib->parent : $objectID;
|
||
}
|
||
|
||
$this->view->groups = $this->loadModel('group')->getPairs();
|
||
$this->view->users = $this->user->getPairs('nocode|noclosed');
|
||
$this->view->objects = $objects;
|
||
$this->view->type = $type;
|
||
$this->view->objectID = $objectID;
|
||
$this->display();
|
||
}
|
||
|
||
/**
|
||
* 编辑一个文档空间。
|
||
* Edit a doc space.
|
||
*
|
||
* @param int $spaceID
|
||
* @access public
|
||
* @return void
|
||
*/
|
||
public function editSpace(int $spaceID)
|
||
{
|
||
$this->commonEditAction($spaceID);
|
||
$this->display();
|
||
}
|
||
|
||
/**
|
||
* 编辑一个文档库。
|
||
* Edit a library.
|
||
*
|
||
* @param int $libID
|
||
* @access public
|
||
* @return void
|
||
*/
|
||
public function editLib(int $libID)
|
||
{
|
||
$this->commonEditAction($libID);
|
||
$this->display();
|
||
}
|
||
|
||
/**
|
||
* 编辑空间和编辑库的公用方法。
|
||
* Edit a lib or space.
|
||
*
|
||
* @param int $libID
|
||
* @access public
|
||
* @return void
|
||
*/
|
||
public function commonEditAction($libID)
|
||
{
|
||
if(!common::hasPriv('doc', 'editSpace') && !common::hasPriv('doc', 'editLib')) return;
|
||
$lib = $this->doc->getLibByID($libID);
|
||
|
||
/* 项目模板下setMenu会修改common语言项,所以执行文档要先执行setAclForCreateLib。 */
|
||
if($lib->type != 'project') $this->docZen->setAclForEditLib($lib);
|
||
$this->doc->setMenuByType($lib->type, (int)zget($lib, $lib->type, 0), (int)$libID);
|
||
if($lib->type == 'project') $this->docZen->setAclForEditLib($lib);
|
||
|
||
if(!empty($_POST))
|
||
{
|
||
$this->lang->doc->name = $this->lang->nameAB;
|
||
$libData = form::data($this->config->doc->form->editlib)->get();
|
||
if(dao::isError()) return $this->send(array('result' => 'fail', 'message' => dao::getError()));
|
||
|
||
$changes = $this->doc->updateLib($libID, $libData);
|
||
if(dao::isError()) $this->send(array('result' => 'fail', 'message' => dao::getError()));
|
||
|
||
if($changes)
|
||
{
|
||
$object = ($lib->type == 'custom' && $lib->parent == 0) ? 'docspace' : 'doclib';
|
||
$actionID = $this->action->create($object, $libID, 'edited');
|
||
$this->action->logHistory($actionID, $changes);
|
||
}
|
||
|
||
$lib = $this->doc->getLibByID($libID);
|
||
$docAppActions = array();
|
||
$docAppActions[] = array('update', ($lib->parent == 0) ? 'space' : 'lib', $lib);
|
||
$docAppActions[] = array('home:loadHomeLibs');
|
||
$docAppActions[] = array('list:load');
|
||
return $this->send(array('message' => $this->lang->saveSuccess, 'result' => 'success', 'closeModal' => true, 'docApp' => $docAppActions));
|
||
}
|
||
|
||
if(!empty($lib->product)) $this->view->object = $this->product->getByID($lib->product);
|
||
if(!empty($lib->project) && empty($lib->execution)) $this->view->object = $this->project->getByID($lib->project);
|
||
if(!empty($lib->execution))
|
||
{
|
||
$execution = $this->execution->getByID($lib->execution);
|
||
if($execution->type == 'stage')
|
||
{
|
||
if($execution->grade > 1)
|
||
{
|
||
$parentExecutions = $this->execution->getPairsByList(explode(',', trim($execution->path, ',')), 'stage,kanban,sprint');
|
||
$execution->name = implode('/', $parentExecutions);
|
||
}
|
||
|
||
$this->lang->doc->execution = str_replace($this->lang->executionCommon, $this->lang->project->stage, $this->lang->doc->execution);
|
||
}
|
||
|
||
$this->view->object = $execution;
|
||
}
|
||
|
||
$this->view->lib = $lib;
|
||
$this->view->groups = $this->loadModel('group')->getPairs();
|
||
$this->view->users = $this->user->getPairs('noletter|noclosed', $lib->users);
|
||
$this->view->libID = $libID;
|
||
}
|
||
|
||
/**
|
||
* 删除一个文档空间。
|
||
* Delete a doc space.
|
||
*
|
||
* @param int $libID
|
||
* @access public
|
||
* @return void
|
||
*/
|
||
public function deleteSpace(int $libID)
|
||
{
|
||
$this->commonDeleteAction($libID);
|
||
}
|
||
|
||
/**
|
||
* 删除一个文档库。
|
||
* Delete a library.
|
||
*
|
||
* @param int $libID
|
||
* @access public
|
||
* @return void
|
||
*/
|
||
public function deleteLib(int $libID)
|
||
{
|
||
$this->commonDeleteAction($libID);
|
||
}
|
||
|
||
/**
|
||
* 删除空间和删除库的公用方法。
|
||
* Delete a lib or space.
|
||
*
|
||
* @param int $libID
|
||
* @access public
|
||
* @return void
|
||
*/
|
||
public function commonDeleteAction(int $libID)
|
||
{
|
||
if(in_array($libID, array('product', 'execution'))) return;
|
||
|
||
$lib = $this->doc->getLibByID($libID);
|
||
if(!empty($lib->main)) return $this->send(array('result' => 'fail', 'message' => $this->lang->doc->errorMainSysLib, 'load' => array('alert' => $this->lang->doc->errorMainSysLib)));
|
||
|
||
$this->dao->update(TABLE_DOCLIB)->set('deleted')->eq('1')->where('id')->eq($libID)->exec();
|
||
|
||
$object = ($lib->type == 'custom' && $lib->parent == 0) ? 'docspace' : 'doclib';
|
||
$this->loadModel('action')->create($object, $libID, 'deleted', '', ACTIONMODEL::CAN_UNDELETED);
|
||
|
||
$moduleName = 'doc';
|
||
$objectType = $lib->type;
|
||
$methodName = zget($this->config->doc->spaceMethod, $objectType);
|
||
if($this->app->tab == 'doc') return $this->send(array('result' => 'success', 'load' => $this->createLink($moduleName, $methodName), 'app' => $this->app->tab));
|
||
|
||
$objectID = strpos(',product,project,execution,', ",$objectType,") !== false ? $lib->{$objectType} : 0;
|
||
if($this->app->tab == 'execution' && $objectType == 'execution')
|
||
{
|
||
$moduleName = 'execution';
|
||
$methodName = 'doc';
|
||
}
|
||
$browseLink = $this->createLink($moduleName, $methodName, "objectID=$objectID");
|
||
|
||
return $this->send(array('result' => 'success', 'load' => $browseLink, 'app' => $this->app->tab));
|
||
}
|
||
|
||
/**
|
||
* 文档模板列表。
|
||
* Browse template list.
|
||
*
|
||
* @param int $libID
|
||
* @param string $type
|
||
* @param mixed $docID
|
||
* @param string $orderBy
|
||
* @param int $recPerPage
|
||
* @param int $pageID
|
||
* @access public
|
||
* @return void
|
||
*/
|
||
public function browseTemplate(int $libID = 0, string $type = 'all', mixed $docID = 0, string $orderBy = 'id_desc', int $recPerPage = 20, int $pageID = 1, string $mode = 'home')
|
||
{
|
||
/* 添加内置的范围、分类、文档模板。*/
|
||
/* Add the built-in scopes and type and doc template. */
|
||
$builtInScopes = $this->dao->select('id')->from(TABLE_DOCLIB)->where('type')->eq('template')->andWhere('main')->eq('1')->fetchAll();
|
||
if(empty($builtInScopes))
|
||
{
|
||
$this->doc->addBuiltInScopes();
|
||
$this->doc->addBuiltInDocTemplateType();
|
||
$this->doc->addBuiltInDocTemplateByType();
|
||
}
|
||
|
||
$this->lang->doc->menu->template['alias'] .= ',' . $this->app->rawMethod;
|
||
$libModules = $this->doc->getTemplateModules($libID);
|
||
if($mode == 'create' && empty($libModules)) return $this->send(array('result' => 'success', 'load' => array('alert' => $this->lang->docTemplate->createTypeFirst)));
|
||
|
||
$templateList = $this->doc->getDocTemplateList(0, $type, $orderBy);
|
||
$templateList = $this->doc->filterDeletedDocs($templateList);
|
||
$templateList = $this->doc->filterPrivDocs($templateList, 'template');
|
||
$allModules = $this->doc->getTemplateModules();
|
||
$allModules = array_column($allModules, 'fullName', 'id');
|
||
foreach($templateList as $template) $template->moduleName = zget($allModules, $template->module);
|
||
|
||
$docVersion = 0;
|
||
if(is_string($docID) && strpos($docID, '_') !== false) list($docID, $docVersion) = explode('_', $docID);
|
||
|
||
$this->view->title = $this->lang->doc->template;
|
||
$this->view->libID = $libID;
|
||
$this->view->users = $this->loadModel('user')->getPairs('noclosed,noletter');
|
||
$this->view->templateList = $templateList;
|
||
$this->view->docID = $docID;
|
||
$this->view->docVersion = $docVersion;
|
||
$this->view->orderBy = $orderBy;
|
||
$this->view->recPerPage = $recPerPage;
|
||
$this->view->pageID = $pageID;
|
||
$this->view->mode = $mode;
|
||
$this->view->hasModules = count($libModules) ? true : false;
|
||
$this->view->scopes = $this->doc->getTemplateScopes();
|
||
$this->display();
|
||
}
|
||
|
||
/**
|
||
* 创建一个模板类型。
|
||
* Add a template type.
|
||
*
|
||
* @param int $scope
|
||
* @param int|string $parentModule
|
||
* @access public
|
||
* @return void
|
||
*/
|
||
public function addTemplateType(int $scope, int|string $parentModule = '')
|
||
{
|
||
$moduleList = $this->doc->getTemplateModules($scope, '1');
|
||
|
||
if(!empty($_POST))
|
||
{
|
||
$this->lang->doc->name = $this->lang->docTemplate->typeName;
|
||
$moduleData = form::data($this->config->doc->form->addTemplateType)
|
||
->setDefault('type', 'docTemplate')
|
||
->setDefault('path', '')
|
||
->get();
|
||
$moduleData->grade = $moduleData->parent === 0 ? 1 : 2;
|
||
if(dao::isError()) return $this->send(array('result' => 'fail', 'message' => dao::getError()));
|
||
|
||
$this->doc->addTemplateType($moduleData);
|
||
if(dao::isError()) return $this->send(array('result' => 'fail', 'message' => dao::getError()));
|
||
|
||
return $this->docZen->responseAfterAddTemplateType($scope);
|
||
}
|
||
|
||
$moduleItems = array();
|
||
if($parentModule === 0)
|
||
{
|
||
$moduleItems[] = array('value' => 0, 'text' => '/');
|
||
}
|
||
else
|
||
{
|
||
foreach($moduleList as $module) $moduleItems[] = array('value' => $module->id, 'text' => '/' . $module->name);
|
||
$moduleItems[] = array('value' => 0, 'text' => '/');
|
||
}
|
||
|
||
$scopeList = $this->doc->getTemplateScopes();
|
||
|
||
$this->view->scope = $scope;
|
||
$this->view->scopes = $this->doc->getScopeItems($scopeList);
|
||
$this->view->moduleItems = $moduleItems;
|
||
$this->view->parentModule = $parentModule === '' ? current($moduleItems) : $parentModule;
|
||
$this->display();
|
||
}
|
||
|
||
/**
|
||
* 删除一个模板类型。
|
||
* Delete a template type.
|
||
*
|
||
* @param int $moduleID
|
||
* @access public
|
||
* @return void
|
||
*/
|
||
public function deleteTemplateType(int $moduleID)
|
||
{
|
||
$templates = $this->doc->getTemplatesByType($moduleID);
|
||
if(empty($templates))
|
||
{
|
||
$this->dao->update(TABLE_MODULE)->set('deleted')->eq('1')->where('id')->eq($moduleID)->andWhere('type')->eq('docTemplate')->exec();
|
||
$this->dao->update(TABLE_MODULE)->set('deleted')->eq('1')->where('parent')->eq($moduleID)->andWhere('type')->eq('docTemplate')->exec();
|
||
return $this->sendSuccess(array('load' => true));
|
||
}
|
||
else
|
||
{
|
||
return $this->send(array('result' => 'fail', 'message' => $this->lang->docTemplate->errorDeleteType));
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 编辑一个模板类型。
|
||
* Edit a template type.
|
||
*
|
||
* @param int $moduleID
|
||
* @access public
|
||
* @return void
|
||
*/
|
||
public function editTemplateType(int $moduleID)
|
||
{
|
||
echo $this->fetch('tree', 'edit', "moduleID={$moduleID}&type=docTemplate");
|
||
}
|
||
|
||
/**
|
||
* 创建一个文档模板。
|
||
* Create a doc template.
|
||
*
|
||
* @param int $moduleID
|
||
* @access public
|
||
* @return void
|
||
*/
|
||
public function createTemplate(int $moduleID = 0)
|
||
{
|
||
if(!empty($_POST))
|
||
{
|
||
$this->lang->doc->title = $_POST['type'] == 'chapter' ? $this->lang->doc->chapterName : $this->lang->docTemplate->title;
|
||
|
||
helper::setcookie('lastDocModule', $moduleID);
|
||
$docData = form::data()
|
||
->setDefault('addedBy', $this->app->user->account)
|
||
->setDefault('editedBy', $this->app->user->account)
|
||
->get();
|
||
if(empty($docData->module)) return $this->sendError(sprintf($this->lang->error->notempty, $this->lang->docTemplate->module));
|
||
|
||
if(!empty($docData->parent))
|
||
{
|
||
$parentTemplate = $this->doc->fetchByID((int)$docData->parent);
|
||
$docData->module = $parentTemplate->module;
|
||
$docData->lib = (int)$parentTemplate->lib;
|
||
$docData->acl = $parentTemplate->acl;
|
||
$docData->templateType = $parentTemplate->templateType;
|
||
}
|
||
|
||
$docResult = $this->doc->create($docData);
|
||
if(!$docResult || dao::isError()) return $this->send(array('result' => 'fail', 'message' => dao::getError()));
|
||
return $this->docZen->responseAfterCreate($docResult, 'docTemplate');
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 编辑一个文档。
|
||
* Edit a doc.
|
||
*
|
||
* @param int $docID
|
||
* @access public
|
||
* @return void
|
||
*/
|
||
public function editTemplate(int $docID)
|
||
{
|
||
$doc = $this->doc->getByID($docID);
|
||
if(!empty($_POST))
|
||
{
|
||
$this->lang->doc->module = $this->lang->docTemplate->module;
|
||
$changes = $files = array();
|
||
$docData = form::data()
|
||
->setDefault('editedBy', $this->app->user->account)
|
||
->setIF(!isset($_POST['parent']), 'parent', $doc->parent)
|
||
->setIF(strpos(",$doc->editedList,", ",{$this->app->user->account},") === false, 'editedList', $doc->editedList . ",{$this->app->user->account}")
|
||
->setIF($this->post->type == 'chapter', 'content', $doc->content)
|
||
->setIF($this->post->type == 'chapter', 'rawContent', $doc->rawContent)
|
||
->remove('fromVersion')
|
||
->get();
|
||
|
||
$result = $this->doc->update($docID, $docData);
|
||
if(dao::isError())
|
||
{
|
||
if(!empty(dao::$errors['lib']) || !empty(dao::$errors['keywords'])) return $this->send(array('result' => 'fail', 'message' => dao::getError(), 'callback' => "zui.Modal.open({id: 'modalBasicInfo'});"));
|
||
return $this->send(array('result' => 'fail', 'message' => dao::getError()));
|
||
}
|
||
|
||
$changes = $result['changes'];
|
||
$files = $result['files'];
|
||
return $this->docZen->responseAfterEditTemplate($doc, $changes, $files);
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 上传文档。
|
||
* Upload docs.
|
||
*
|
||
* @param int $docID
|
||
* @param string $objectType product|project|execution|custom
|
||
* @param int $objectID
|
||
* @param int|string $libID
|
||
* @param int $moduleID
|
||
* @param string $docType html|word|ppt|excel|attachment
|
||
* @access public
|
||
* @return void
|
||
*/
|
||
public function uploadDocs(int $docID, string $objectType, int $objectID, int $libID, int $moduleID = 0, string $docType = '')
|
||
{
|
||
if(!empty($_POST))
|
||
{
|
||
/* parent带‘m_’前缀为目录。*/
|
||
if(isset($_POST['parent']) && strpos($_POST['parent'], 'm_') !== false)
|
||
{
|
||
$_POST['module'] = str_replace('m_', '', $_POST['parent']);
|
||
$_POST['parent'] = 0;
|
||
}
|
||
|
||
$libID = (int)$this->post->lib;
|
||
|
||
if(!$libID) return $this->send(array('result' => 'fail', 'message' => array('lib' => sprintf($this->lang->error->notempty, $this->lang->doc->lib))));
|
||
|
||
$doclib = $this->loadModel('doc')->getLibByID($libID);
|
||
$canVisit = $this->docZen->checkPrivForCreate($doclib, $objectType);
|
||
if(!$canVisit) return $this->send(array('result' => 'fail', 'message' => $this->lang->doc->accessDenied));
|
||
|
||
$moduleID = $this->post->module;
|
||
helper::setcookie('lastDocModule', $moduleID);
|
||
|
||
if(!isset($_POST['lib']) && strpos($_POST['module'], '_') !== false) list($_POST['lib'], $_POST['module']) = explode('_', $_POST['module']);
|
||
if($_POST['type'] == 'attachment' && empty($_FILES['files']['name'][0]))
|
||
{
|
||
$this->config->doc->form->create['title']['required'] = false;
|
||
$this->config->doc->form->create['title']['skipRequired'] = true;
|
||
}
|
||
|
||
$this->config->doc->create->requiredFields = trim(str_replace(array(',content,', ',keywords,'), ",", ",{$this->config->doc->create->requiredFields},"), ',');
|
||
|
||
$docData = form::data(!empty($docID) ? $this->config->doc->form->edit : $this->config->doc->form->create)->remove('fromVersion')->get();
|
||
if(empty($docID)) $docData->addedBy = $this->app->user->account;
|
||
if(!empty($docID)) $docData->editedBy = $this->app->user->account;
|
||
|
||
if(!empty($docID))
|
||
{
|
||
$docResult = $this->doc->update($docID, $docData);
|
||
$docData->id = $docID;
|
||
}
|
||
elseif($this->post->uploadFormat == 'combinedDocs')
|
||
{
|
||
$docResult = $this->doc->create($docData);
|
||
}
|
||
else
|
||
{
|
||
$docResult = $this->doc->createSeperateDocs($docData);
|
||
}
|
||
|
||
if(dao::isError()) return $this->send(array('result' => 'fail', 'message' => dao::getError()));
|
||
return !empty($docID) ? $this->send($this->docZen->responseAfterEdit($docData, $docResult['changes'], $docResult['files'], $docResult['deletedFiles'])) : $this->docZen->responseAfterUploadDocs($docResult);
|
||
}
|
||
|
||
if($objectType == 'execution' && $libID) // 此时传入的objectID是projectID,用lib的信息更改回executionID
|
||
{
|
||
$lib = $this->doc->getLibByID($libID);
|
||
$objectID = $this->doc->getObjectIDByLib($lib);
|
||
}
|
||
|
||
$this->docZen->assignVarsForUploadDocs($docID, $objectType, $objectID, $libID, $moduleID, $docType);
|
||
$this->display();
|
||
}
|
||
|
||
/**
|
||
* 创建一个文档。
|
||
* Create a doc.
|
||
*
|
||
* @param string $objectType product|project|execution|custom
|
||
* @param int $objectID
|
||
* @param int|string $libID
|
||
* @param int $moduleID
|
||
* @param string $docType html|word|ppt|excel
|
||
* @param int $appendLib
|
||
* @access public
|
||
* @return void
|
||
*/
|
||
public function create(string $objectType, int $objectID, int $libID, int $moduleID = 0, string $docType = '', int $appendLib = 0)
|
||
{
|
||
if(!empty($_POST))
|
||
{
|
||
/* parent带‘m_’前缀为目录。*/
|
||
if(isset($_POST['parent']) && strpos($_POST['parent'], 'm_') !== false)
|
||
{
|
||
$_POST['module'] = str_replace('m_', '', $_POST['parent']);
|
||
$_POST['parent'] = 0;
|
||
}
|
||
|
||
$libID = (int)$this->post->lib;
|
||
$docLib = $this->loadModel('doc')->getLibByID($libID);
|
||
if($docLib)
|
||
{
|
||
$canVisit = $this->docZen->checkPrivForCreate($docLib, $objectType);
|
||
if(!$canVisit) return $this->send(array('result' => 'fail', 'message' => $this->lang->doc->accessDenied));
|
||
}
|
||
|
||
$moduleID = $this->post->module;
|
||
helper::setcookie('lastDocModule', $moduleID);
|
||
|
||
if(!isset($_POST['lib']) && strpos($_POST['module'], '_') !== false) list($_POST['lib'], $_POST['module']) = explode('_', $_POST['module']);
|
||
|
||
if($_POST['type'] == 'chapter') $this->lang->doc->title = $this->lang->doc->chapterName;
|
||
|
||
$docData = form::data()
|
||
->setDefault('addedBy', $this->app->user->account)
|
||
->setDefault('editedBy', $this->app->user->account)
|
||
->get();
|
||
|
||
if($docData->parent && !$docData->module)
|
||
{
|
||
$parentDoc = $this->doc->getByID($docData->parent);
|
||
$docData->module = $parentDoc->module;
|
||
}
|
||
|
||
$docResult = $this->doc->create($docData);
|
||
if(!$docResult || dao::isError()) return $this->send(array('result' => 'fail', 'message' => dao::getError()));
|
||
return $this->docZen->responseAfterCreate($docResult);
|
||
}
|
||
|
||
$this->docZen->assignVarsForCreate($objectType, $objectID, $libID, $moduleID, $docType);
|
||
|
||
$lib = $this->view->lib;
|
||
if(empty($lib)) return $this->send(array('result' => 'fail', 'message' => $this->lang->doc->errorEmptySpaceLib));
|
||
|
||
$objectID = $this->view->objectID;
|
||
$libData = $this->doc->setMenuByType($lib->type, (int)$objectID, (int)$lib->id, (int)$appendLib);
|
||
if(is_string($libData)) return $this->locate($libData);
|
||
list($libs, $libID, $object, $objectID, $objectDropdown) = $libData;
|
||
if($this->config->edition != 'open') $this->loadModel('file');
|
||
if($lib->type == 'custom' || $lib->type == 'mine') $this->view->spaces = $this->docZen->getAllSpaces($lib->type == 'mine' ? 'onlymine' : 'nomine');
|
||
|
||
$this->view->title = zget($lib, 'name', '', $lib->name . $this->lang->hyphen) . $this->lang->doc->create;
|
||
$this->view->object = $object;
|
||
$this->view->objectDropdown = $objectDropdown;
|
||
$this->view->libTree = $this->doc->getLibTree((int)$libID, $libs, $objectType, (int)$moduleID, (int)$objectID);
|
||
$this->view->linkParams = "objectID={$objectID}&%s&browseType=&orderBy=status,id_desc¶m=0";
|
||
|
||
if(!empty($objectType) && $objectType !== 'custom')
|
||
{
|
||
$objectIDVar = $objectType . 'ID';
|
||
$this->view->$objectIDVar = $objectID;
|
||
}
|
||
$this->display();
|
||
}
|
||
|
||
/**
|
||
* 编辑一个文档。
|
||
* Edit a doc.
|
||
*
|
||
* @param int $docID
|
||
* @param bool $comment
|
||
* @param int $appendLib
|
||
* @access public
|
||
* @return void
|
||
*/
|
||
public function edit(int $docID, bool $comment = false, int $appendLib = 0)
|
||
{
|
||
$doc = $this->doc->getByID($docID);
|
||
if(!empty($_POST))
|
||
{
|
||
/* parent带‘m_’前缀为目录。*/
|
||
if(isset($_POST['parent']) && strpos($_POST['parent'], 'm_') !== false)
|
||
{
|
||
$_POST['module'] = str_replace('m_', '', $_POST['parent']);
|
||
$_POST['parent'] = 0;
|
||
}
|
||
|
||
if(!$doc) return $this->send(array('result' => 'fail', 'message' => $this->lang->doc->errorNotFound));
|
||
|
||
$isOpen = $doc->acl == 'open';
|
||
$currentAccount = $this->app->user->account;
|
||
$isAuthorOrAdmin = $doc->acl == 'private' && ($doc->addedBy == $currentAccount || $this->app->user->admin);
|
||
$isInEditUsers = strpos(",$doc->users,", ",$currentAccount,") !== false;
|
||
$isInEditGroups = false;
|
||
if(!empty($doc->groups))
|
||
{
|
||
foreach($this->app->user->groups as $groupID)
|
||
{
|
||
if(strpos(",$doc->groups,", ",$groupID,") !== false) $isInEditGroups = true;
|
||
}
|
||
}
|
||
|
||
if(!$isOpen && !$isAuthorOrAdmin && !$isInEditUsers && !$isInEditGroups) return $this->send(array('result' => 'fail', 'message' => $this->lang->doc->needEditable));
|
||
|
||
if($doc->type == 'chapter') $this->lang->doc->title = $this->lang->doc->chapterName;
|
||
|
||
$changes = $files = array();
|
||
if($comment == false)
|
||
{
|
||
$docData = form::data()
|
||
->setDefault('editedBy', $this->app->user->account)
|
||
->setDefault('acl', $doc->acl)
|
||
->setIF(strpos(",$doc->editedList,", ",{$this->app->user->account},") === false, 'editedList', $doc->editedList . ",{$this->app->user->account}")
|
||
->setIF(!isset($_POST['module']), 'module', $doc->module)
|
||
->setIF(!isset($_POST['mailto']), 'mailto', $doc->mailto)
|
||
->setIF(!isset($_POST['users']), 'users', $doc->users)
|
||
->setIF(!isset($_POST['groups']), 'groups', $doc->groups)
|
||
->setIF(!isset($_POST['readUsers']), 'readUsers', $doc->readUsers)
|
||
->setIF(!isset($_POST['readGroups']), 'readGroups', $doc->readGroups)
|
||
->setIF(!isset($_POST['fromVersion']), 'fromVersion', $doc->fromVersion)
|
||
->removeIF($this->post->project === false, 'project')
|
||
->removeIF($this->post->product === false, 'product')
|
||
->removeIF($this->post->execution === false, 'execution')
|
||
->get();
|
||
$result = $this->doc->update($docID, $docData);
|
||
if(dao::isError())
|
||
{
|
||
if(!empty(dao::$errors['lib']) || !empty(dao::$errors['keywords'])) return $this->send(array('result' => 'fail', 'message' => dao::getError(), 'callback' => "zui.Modal.open({id: 'modalBasicInfo'});"));
|
||
return $this->send(array('result' => 'fail', 'message' => dao::getError()));
|
||
}
|
||
|
||
$changes = $result['changes'];
|
||
$files = $result['files'];
|
||
}
|
||
|
||
return $this->send($this->docZen->responseAfterEdit($doc, $changes, $files));
|
||
}
|
||
|
||
/* Get doc and set menu. */
|
||
$moduleID = (int)$doc->module;
|
||
$libID = (int)$doc->lib;
|
||
$lib = $this->doc->getLibByID($libID);
|
||
$objectType = isset($lib->type) ? $lib->type : 'custom';
|
||
$objectID = zget($lib, $lib->type, 0);
|
||
if($lib->type == 'custom') $objectID = $lib->parent;
|
||
|
||
if($doc->type == 'text' || $doc->type == 'article')
|
||
{
|
||
echo $this->fetch('doc', 'app', "type=$objectType&spaceID=$objectID&libID=$libID&moduleID=$doc->module&docID=$docID&mode=edit");
|
||
return;
|
||
}
|
||
|
||
$libPairs = $this->doc->getLibs($lib->type, '', $doc->lib, $objectID);
|
||
list($libs, $libID, $object, $objectID, $objectDropdown) = $this->doc->setMenuByType($objectType, $objectID, (int)$doc->lib, (int)$appendLib);
|
||
|
||
if($lib->type == 'custom' || $lib->type == 'mine') $this->view->spaces = $this->docZen->getAllSpaces($lib->type == 'mine' ? 'onlymine' : 'nomine');
|
||
$this->docZen->setObjectsForEdit($lib->type, $objectID);
|
||
|
||
$this->view->title = $lib->name . $this->lang->hyphen . $this->lang->doc->edit;
|
||
$this->view->doc = $doc;
|
||
$this->view->optionMenu = $this->loadModel('tree')->getOptionMenu($libID, 'doc', 0);
|
||
$this->view->type = $lib->type;
|
||
$this->view->libs = $libPairs;
|
||
$this->view->lib = $lib;
|
||
$this->view->libID = $libID;
|
||
$this->view->libTree = $this->doc->getLibTree($libID, $libs, $objectType, $moduleID, (int)$objectID, '', 0, $docID);
|
||
$this->view->groups = $this->loadModel('group')->getPairs();
|
||
$this->view->users = $this->user->getPairs('noletter|noclosed|nodeleted', $doc->users);
|
||
$this->view->files = $this->loadModel('file')->getByObject('doc', $docID);
|
||
$this->view->objectType = $objectType;
|
||
$this->view->object = $object;
|
||
$this->view->objectID = $objectID;
|
||
$this->view->objectDropdown = $objectDropdown;
|
||
$this->view->moduleID = $moduleID;
|
||
$this->view->spaceType = $objectType;
|
||
$this->view->productID = $doc->product;
|
||
$this->view->projectID = $doc->project;
|
||
$this->view->executionID = $doc->execution;
|
||
$this->view->linkParams = "objectID={$objectID}&%s&browseType=&orderBy=status,id_desc¶m=0";
|
||
$this->view->otherEditing = $this->doc->checkOtherEditing($docID);
|
||
$this->display();
|
||
}
|
||
|
||
/**
|
||
* 删除一个文档。
|
||
* Delete a doc.
|
||
*
|
||
* @param int $docID
|
||
* @access public
|
||
* @return void
|
||
*/
|
||
public function delete(int $docID)
|
||
{
|
||
$this->doc->delete(TABLE_DOC, $docID);
|
||
|
||
/* Delete doc files. */
|
||
$doc = $this->doc->getByID($docID);
|
||
if($doc->files) $this->doc->deleteFiles(array_keys($doc->files));
|
||
|
||
if(dao::isError()) $this->send(array('result' => 'fail', 'message' => dao::getError()));
|
||
return $this->sendSuccess(array('load' => $this->session->docList ? $this->session->docList : $this->createLink('doc', 'index')));
|
||
}
|
||
|
||
/**
|
||
* 删除一个文档模板。
|
||
* Delete a doctemplate.
|
||
*
|
||
* @param int $templateID
|
||
* @access public
|
||
* @return void
|
||
*/
|
||
public function deleteTemplate(int $templateID)
|
||
{
|
||
$this->doc->deleteTemplate($templateID);
|
||
|
||
/* Delete template files. */
|
||
$template = $this->doc->getByID($templateID);
|
||
if($template->files) $this->doc->deleteFiles(array_keys($template->files));
|
||
|
||
if(dao::isError()) $this->send(array('result' => 'fail', 'message' => dao::getError()));
|
||
|
||
$link = $this->createLink('doc', 'browseTemplate');
|
||
return $this->sendSuccess(array('load' => $link));
|
||
}
|
||
|
||
/**
|
||
* 收藏一个文档。
|
||
* Collect a doc.
|
||
*
|
||
* @param int $objectID
|
||
* @access public
|
||
* @return void
|
||
*/
|
||
public function collect(int $objectID)
|
||
{
|
||
$action = $this->doc->getActionByObject($objectID, 'collect');
|
||
if($action)
|
||
{
|
||
$this->doc->deleteAction($action->id);
|
||
$this->action->create('doc', $objectID, 'uncollected');
|
||
}
|
||
else
|
||
{
|
||
$this->doc->createAction($objectID, 'collect');
|
||
$this->action->create('doc', $objectID, 'collected');
|
||
}
|
||
|
||
if($this->viewType == 'json') $this->send(array('status' => $action ? 'no' : 'yes'));
|
||
return $this->send(array('result' => 'success', 'message' => $action ? $this->lang->doc->cancelCollection : $this->lang->doc->collectSuccess, 'load' => true, 'status' => $action ? 'no' : 'yes'));
|
||
}
|
||
|
||
/**
|
||
*
|
||
* AJAX: 获取对象的目录。
|
||
* Ajax get modules by object.
|
||
*
|
||
* @param string $objectType project|product|custom|mine
|
||
* @param int $objectID
|
||
* @param string $docType doc|api
|
||
* @param int $docID
|
||
* @param int $libID
|
||
* @access public
|
||
* @return void
|
||
*/
|
||
public function ajaxGetModules(string $objectType, int $objectID, string $docType = 'doc', int $docID = 0, int $libID = 0)
|
||
{
|
||
if($objectType != 'mine' && empty($objectID)) return print(json_encode(array()));
|
||
|
||
if($docType == 'doc')
|
||
{
|
||
$unclosed = strpos($this->config->doc->custom->showLibs, 'unclosed') !== false ? 'unclosedProject' : '';
|
||
$libPairs = $this->doc->getLibs($objectType, $unclosed, '', (int)$objectID);
|
||
}
|
||
elseif($docType == 'api')
|
||
{
|
||
$libs = $this->doc->getApiLibs(0, $objectType, $objectID);
|
||
$libPairs = array();
|
||
foreach($libs as $lib) $libPairs[$lib->id] = $lib->name;
|
||
}
|
||
$libItems = array();
|
||
foreach($libPairs as $id => $name) $libItems[] = array('text' => $name, 'value' => $id, 'keys' => $name);
|
||
|
||
$moduleItems = array();
|
||
$libID = $libID ? $libID : key($libPairs);
|
||
if($libID)
|
||
{
|
||
$chapterAndDocs = $this->doc->getDocsOfLibs(array($libID), $objectType, $docID);
|
||
$modulePairs = empty($libID) ? array() : $this->loadModel('tree')->getOptionMenu($libID, 'doc', 0);
|
||
$nestedDocs = $this->doc->buildNestedDocs($chapterAndDocs, $modulePairs);
|
||
$moduleItems = array_merge(array(array('text' => '/', 'value' => 'm_0')), array_values($nestedDocs));
|
||
}
|
||
|
||
return print(json_encode(array('libs' => $libItems, 'modules' => $moduleItems)));
|
||
}
|
||
|
||
/**
|
||
*
|
||
* AJAX: 获取范围下的类型。
|
||
* Ajax get types of scope.
|
||
*
|
||
* @param int $libID
|
||
* @access public
|
||
* @return json
|
||
*/
|
||
public function ajaxGetScopeTypes(int $libID = 0)
|
||
{
|
||
$optionMenu = $this->loadModel('tree')->getOptionMenu($libID, 'docTemplate', 0, 'all', 'nodeleted', 'all');
|
||
$types = array();
|
||
foreach($optionMenu as $menuID => $menu)
|
||
{
|
||
if(empty($menuID)) continue;
|
||
$types[] = array('text' => $menu, 'value' => $menuID, 'keys' => $menu);
|
||
}
|
||
return print(json_encode($types));
|
||
}
|
||
|
||
/**
|
||
* AJAX: 通过空间类型获取文档库。
|
||
* AJAX: Get libs by type.
|
||
*
|
||
* @param string $type mine|product|project|nolink|custom
|
||
* @param string $docType doc|api
|
||
* @access public
|
||
* @return void
|
||
*/
|
||
public function ajaxGetLibsByType(string $type, string $docType = 'doc', string $extra = '')
|
||
{
|
||
$libPairs = array();
|
||
if($docType == 'doc')
|
||
{
|
||
$unclosed = strpos($this->config->doc->custom->showLibs, 'unclosed') !== false ? 'unclosedProject' : '';
|
||
if($extra) $unclosed .= ",$extra";
|
||
$libPairs = $this->doc->getLibs($type, $unclosed);
|
||
}
|
||
elseif($docType == 'api')
|
||
{
|
||
$libs = $this->doc->getApiLibs(0, 'nolink');
|
||
$libPairs = array();
|
||
foreach($libs as $libID => $lib) $libPairs[$libID] = $lib->name;
|
||
}
|
||
|
||
$libItems = array();
|
||
foreach($libPairs as $id => $name) $libItems[] = array('text' => $name, 'value' => $id, 'keys' => $name);
|
||
|
||
$moduleItems = array();
|
||
$libID = key($libPairs);
|
||
if($libID)
|
||
{
|
||
$optionMenu = $this->loadModel('tree')->getOptionMenu($libID, $docType, 0);
|
||
foreach($optionMenu as $id => $name) $moduleItems[] = array('text' => $name, 'value' => $id, 'keys' => $name);
|
||
}
|
||
|
||
return print(json_encode(array('libs' => $libItems, 'modules' => $moduleItems)));
|
||
}
|
||
|
||
/**
|
||
* Ajax: 获取白名单。
|
||
* Ajax: Get whitelist.
|
||
*
|
||
* @param int $doclibID
|
||
* @param string $acl open|custom|private
|
||
* @param string $control user|group
|
||
* @param int $docID
|
||
* @access public
|
||
* @return string
|
||
*/
|
||
public function ajaxGetWhitelist(int $doclibID, string $acl = '', string $control = '', int $docID = 0)
|
||
{
|
||
$doclib = $this->doc->getLibByID($doclibID);
|
||
$users = $this->user->getPairs('noletter|noempty|noclosed');
|
||
if($control == 'group')
|
||
{
|
||
if($doclib->acl == 'private') return print('private');
|
||
|
||
$groupItems = array();
|
||
$groups = $this->loadModel('group')->getPairs();
|
||
foreach($groups as $groupID => $groupName) $groupItems[] = array('text' => $groupName, 'value' => $groupID, 'keys' => $groupName);
|
||
return print(json_encode($groupItems));
|
||
}
|
||
|
||
if($doclib->acl == 'private') return print('private');
|
||
|
||
$userItems = array();
|
||
foreach($users as $account => $realname)
|
||
{
|
||
if($doclib->acl == 'private' && strpos($doclib->users, (string)$account) === false ) unset($users[$account]);
|
||
$userItems[] = array('text' => $realname, 'value' => $account, 'keys' => $realname);
|
||
}
|
||
return print(json_encode($userItems));
|
||
}
|
||
|
||
/**
|
||
* 附件库。
|
||
* Show files.
|
||
*
|
||
* @param string $type
|
||
* @param int $objectID
|
||
* @param string $viewType
|
||
* @param string $browseType
|
||
* @param int $param
|
||
* @param string $orderBy
|
||
* @param int $recTotal
|
||
* @param int $recPerPage
|
||
* @param int $pageID
|
||
* @param string $searchTitle
|
||
* @access public
|
||
* @return void
|
||
*/
|
||
public function showFiles(string $type, int $objectID, string $viewType = '', string $browseType = '', int $param = 0, string $orderBy = 'id_desc', int $recTotal = 0, int $recPerPage = 20, int $pageID = 1, string $searchTitle = '')
|
||
{
|
||
$this->loadModel('file');
|
||
if(empty($viewType)) $viewType = !empty($_COOKIE['docFilesViewType']) ? $this->cookie->docFilesViewType : 'list';
|
||
helper::setcookie('docFilesViewType', $viewType, $this->config->cookieLife, $this->config->webRoot, '', $this->config->cookieSecure, true);
|
||
|
||
$objects = $this->doc->getOrderedObjects($type, 'nomerge', $objectID);
|
||
list($libs, $libID, $object, $objectID, $objectDropdown) = $this->doc->setMenuByType($type, $objectID, 0);
|
||
|
||
$object = $this->doc->getObjectByID($type, $objectID);
|
||
if(empty($_POST) && !empty($searchTitle)) $this->post->title = $searchTitle;
|
||
|
||
$this->session->set('storyList', $this->app->getURI(true), 'doc');
|
||
$this->session->set('bugList', $this->app->getURI(true), 'doc');
|
||
|
||
/* Load pager. */
|
||
$rawMethod = $this->app->rawMethod;
|
||
$this->app->rawMethod = 'showFiles';
|
||
$this->app->loadClass('pager', $static = true);
|
||
$pager = new pager($recTotal, $recPerPage, $pageID);
|
||
$this->app->rawMethod = $rawMethod;
|
||
|
||
$files = $this->doc->getLibFiles($type, $objectID, $browseType, (int)$param, $orderBy, $pager);
|
||
$fileIcon = $this->doc->getFileIcon($files);
|
||
$sourcePairs = $this->doc->getFileSourcePairs($files);
|
||
|
||
if($this->app->tab != 'doc')
|
||
{
|
||
$objectVar = $this->app->tab . 'ID';
|
||
$this->view->{$objectVar} = $objectID;
|
||
}
|
||
|
||
$this->docZen->buildSearchFormForShowFiles($type, $objectID, $viewType, $param);
|
||
|
||
$this->view->title = $object->name;
|
||
$this->view->type = $type;
|
||
$this->view->object = $object;
|
||
$this->view->files = $this->docZen->processFiles($files, $fileIcon, $sourcePairs);
|
||
$this->view->fileIcon = $fileIcon;
|
||
$this->view->sourcePairs = $sourcePairs;
|
||
$this->view->users = $this->loadModel('user')->getPairs('noletter');
|
||
$this->view->pager = $pager;
|
||
$this->view->viewType = $viewType;
|
||
$this->view->orderBy = $orderBy;
|
||
$this->view->objectID = $objectID;
|
||
$this->view->canBeChanged = common::canModify($type, $object); // Determines whether an object is editable.
|
||
$this->view->summary = $this->doc->summary($files);
|
||
$this->view->libTree = $this->doc->getLibTree(0, $libs, $type, 0, $objectID);
|
||
$this->view->objectDropdown = $objectDropdown;
|
||
$this->view->searchTitle = $searchTitle;
|
||
$this->view->linkParams = "objectID=$objectID&%s&browseType=&orderBy=status,id_desc¶m=0";
|
||
$this->view->spaceType = $type;
|
||
$this->view->objectType = $type;
|
||
$this->view->browseType = $browseType;
|
||
$this->view->param = $param;
|
||
$this->view->libID = 0;
|
||
$this->view->moduleID = 0;
|
||
|
||
$this->display();
|
||
}
|
||
|
||
/**
|
||
* 文档详情页面。
|
||
* Document details page.
|
||
*
|
||
* @param string|int $docID
|
||
* @param int $version
|
||
* @access public
|
||
* @return void
|
||
*/
|
||
public function view(string|int $docID = 0, int $version = 0)
|
||
{
|
||
$isApi = is_string($docID) && strpos($docID, 'api.') === 0;
|
||
$docID = $isApi ? (int)str_replace('api.', '', $docID) : (int)$docID;
|
||
$doc = $isApi ? $this->loadModel('api')->getByID($docID, $version) : $this->doc->getByID($docID, $version, true);
|
||
$docParam = $version ? ($docID . '_' . $version) : $docID;
|
||
if($isApi) $docParam = 'api.' . $docParam;
|
||
if(!$doc || !isset($doc->id))
|
||
{
|
||
if(defined('RUN_MODE') && RUN_MODE == 'api') return $this->send(array('status' => 'fail', 'code' => 404, 'message' => '404 Not found'));
|
||
return $this->sendError($this->lang->notFound, $this->inlink('index'));
|
||
}
|
||
|
||
$_SESSION["doc_{$doc->id}_nopriv"] = '';
|
||
if(!$isApi && !$this->doc->checkPrivDoc($doc))
|
||
{
|
||
$user = $this->loadModel('user')->getByID($doc->addedBy);
|
||
$realname = $user->deleted ? $user->account : $user->realname;
|
||
$errorMessage = empty($_SESSION["doc_{$doc->id}_nopriv"]) ? sprintf($this->lang->doc->cannotView, $realname) : $_SESSION["doc_{$doc->id}_nopriv"];
|
||
unset($_SESSION["doc_{$doc->id}_nopriv"]);
|
||
return $this->sendError($errorMessage, inlink('index'));
|
||
}
|
||
unset($_SESSION["doc_{$doc->id}_nopriv"]);
|
||
|
||
if(!empty($doc->templateType))
|
||
{
|
||
echo $this->fetch('doc', 'browseTemplate', "libID=$doc->lib&type=all&docID=$docParam&orderBy=id_desc&recPerPage=20&pageID=1&mode=view");
|
||
return;
|
||
}
|
||
|
||
$lib = $this->doc->getLibByID((int)$doc->lib);
|
||
$objectType = isset($lib->type) ? $lib->type : 'custom';
|
||
if($objectType == 'api')
|
||
{
|
||
if(isset($lib->product) && $lib->product) list($objectType, $objectID) = array('product', $lib->product);
|
||
if(isset($lib->project) && $lib->project) list($objectType, $objectID) = array('project', $lib->project);
|
||
}
|
||
else
|
||
{
|
||
if($this->app->tab === 'project' && $objectType === 'execution') $objectType = 'project';
|
||
$objectID = $this->doc->getObjectIDByLib($lib, $objectType);
|
||
}
|
||
|
||
/* Get doc. */
|
||
if($docID) $this->doc->createAction($docID, 'view');
|
||
|
||
$this->view->title = $doc->title;
|
||
$libID = isset($lib->id) ? $lib->id : 0;
|
||
echo $this->fetch('doc', 'app', "type=$objectType&spaceID=$objectID&libID=$libID&moduleID=$doc->module&docID=$docParam&mode=view");
|
||
}
|
||
|
||
/**
|
||
* 产品/项目/执行/团队空间。
|
||
* ProductSpace/ProjectSpace/ExecutionSpace/TeamSpace.
|
||
*
|
||
* @param string $type custom|product|project|execution|doctemplate
|
||
* @param int $objectID
|
||
* @param int $libID
|
||
* @param int $moduleID
|
||
* @param string $browseType all|draft|bysearch
|
||
* @param string $orderBy
|
||
* @param int $param
|
||
* @param int $recTotal
|
||
* @param int $recPerPage
|
||
* @param int $pageID
|
||
* @access public
|
||
* @return void
|
||
*/
|
||
public function tableContents(string $type = 'custom', int $objectID = 0, int $libID = 0, int $moduleID = 0, string $browseType = 'all', string $orderBy = 'order_asc', int $param = 0, int $recTotal = 0, int $recPerPage = 20, int $pageID = 1)
|
||
{
|
||
$this->docZen->setSpacePageStorage($type, $browseType, $objectID, $libID, $moduleID, $param);
|
||
|
||
if($moduleID) $libID = $this->tree->getById($moduleID)->root;
|
||
$isFirstLoad = $libID == 0 ? true : false;
|
||
if(empty($browseType)) $browseType = 'all';
|
||
|
||
$libData = $this->doc->setMenuByType($type, $objectID, $libID);
|
||
if(is_string($libData)) return $this->locate($libData);
|
||
list($libs, $libID, $object, $objectID, $objectDropdown) = $libData;
|
||
|
||
$libID = (int)$libID;
|
||
$lib = $this->doc->getLibByID($libID);
|
||
$libType = isset($lib->type) && $lib->type == 'api' ? 'api' : 'lib';
|
||
|
||
/* Build the search form. */
|
||
$queryID = $browseType == 'bySearch' ? $param : 0;
|
||
$queryID = $queryID == 'myQueryID' ? 0 : $queryID;
|
||
$params = "objectID={$objectID}&libID={$libID}&moduleID=0&browseType=bySearch&orderBy={$orderBy}¶m=myQueryID";
|
||
if($this->app->rawMethod == 'tablecontents') $params = "type={$type}&" . $params;
|
||
$actionURL = $this->createLink($this->app->rawModule, $this->app->rawMethod, $params);
|
||
if($libType == 'api') $this->loadModel('api')->buildSearchForm($lib, $queryID, $actionURL, $libs, $type);
|
||
if($libType != 'api') $this->doc->buildSearchForm($libID, $libs, $queryID, $actionURL, $type);
|
||
|
||
$this->docZen->assignApiVarForSpace($type, $browseType, $libType, $libID, $libs, $objectID, $moduleID, $queryID, $orderBy, $param, $recTotal, $recPerPage, $pageID);
|
||
|
||
/* For product drop menu. */
|
||
if(in_array($type, array('product', 'project', 'execution')))
|
||
{
|
||
$objectKey = $type . 'ID';
|
||
$this->view->$objectKey = $objectID;
|
||
}
|
||
|
||
$isOrderByOrder = $orderBy == 'order_asc';
|
||
$isNotCustomLib = $lib && !($lib->type == 'custom' && $lib->parent == 0);
|
||
$canUpdateOrder = $isOrderByOrder && $isNotCustomLib && common::hasPriv('doc', 'sortDoc');
|
||
|
||
$this->view->title = $type == 'custom' ? $this->lang->doc->tableContents : $object->name . $this->lang->hyphen . $this->lang->doc->tableContents;
|
||
$this->view->type = $type;
|
||
$this->view->objectType = $type;
|
||
$this->view->spaceType = $type;
|
||
$this->view->browseType = $browseType;
|
||
$this->view->isFirstLoad = $isFirstLoad;
|
||
$this->view->param = $queryID;
|
||
$this->view->users = $this->user->getPairs('noletter');
|
||
$this->view->libTree = $this->doc->getLibTree($libID, $libs, $type, $moduleID, $objectID, $browseType, (int)$param);
|
||
$this->view->libID = $libID;
|
||
$this->view->moduleID = $moduleID;
|
||
$this->view->objectDropdown = $objectDropdown;
|
||
$this->view->lib = $lib;
|
||
$this->view->libType = $libType;
|
||
$this->view->objectID = $objectID;
|
||
$this->view->orderBy = $orderBy;
|
||
$this->view->release = $browseType == 'byrelease' ? $param : 0;
|
||
$this->view->exportMethod = $libType == 'api' ? 'export' : $type . '2export';
|
||
$this->view->linkParams = "objectID={$objectID}&%s&browseType=&orderBy={$orderBy}¶m=0";
|
||
$this->view->canUpdateOrder = $canUpdateOrder;
|
||
|
||
$this->display();
|
||
}
|
||
|
||
/**
|
||
* 产品空间。
|
||
* Product space.
|
||
*
|
||
* @param int $objectID
|
||
* @param int $libID
|
||
* @param int $moduleID
|
||
* @param string $browseType all|draft|bysearch
|
||
* @param string $orderBy
|
||
* @param int $param
|
||
* @param int $recTotal
|
||
* @param int $recPerPage
|
||
* @param int $pageID
|
||
* @access public
|
||
* @return void
|
||
*/
|
||
public function productSpace(int $objectID = 0, int $libID = 0, int $moduleID = 0, string $browseType = 'all', string $orderBy = '', int $param = 0, int $recTotal = 0, int $recPerPage = 20, int $pageID = 1, string $mode = '', int $docID = 0, string $search = '')
|
||
{
|
||
$noSpace = $this->app->tab != 'doc';
|
||
$mode = empty($mode) && $noSpace ? 'list' : $mode;
|
||
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");
|
||
}
|
||
|
||
/**
|
||
* 项目空间。
|
||
* Project space.
|
||
*
|
||
* @param int $objectID
|
||
* @param int $libID
|
||
* @param int $moduleID
|
||
* @param string $browseType all|draft|bysearch
|
||
* @param string $orderBy
|
||
* @param int $param
|
||
* @param int $recTotal
|
||
* @param int $recPerPage
|
||
* @param int $pageID
|
||
* @access public
|
||
* @return void
|
||
*/
|
||
public function projectSpace(int $objectID = 0, int $libID = 0, int $moduleID = 0, string $browseType = 'all', string $orderBy = '', int $param = 0, int $recTotal = 0, int $recPerPage = 20, int $pageID = 1, string $mode = '', int $docID = 0, string $search = '')
|
||
{
|
||
$noSpace = $this->app->tab != 'doc';
|
||
$mode = empty($mode) && $noSpace ? 'list' : $mode;
|
||
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");
|
||
}
|
||
|
||
/**
|
||
* 团队空间。
|
||
* Team space.
|
||
*
|
||
* @param int $objectID
|
||
* @param int $libID
|
||
* @param int $moduleID
|
||
* @param string $browseType all|draft|bysearch
|
||
* @param string $orderBy
|
||
* @param int $param
|
||
* @param int $recTotal
|
||
* @param int $recPerPage
|
||
* @param int $pageID
|
||
* @access public
|
||
* @return void
|
||
*/
|
||
public function teamSpace(int $objectID = 0, int $libID = 0, int $moduleID = 0, string $browseType = 'all', string $orderBy = '', int $param = 0, int $recTotal = 0, int $recPerPage = 20, int $pageID = 1, string $mode = '', int $docID = 0, string $search = '')
|
||
{
|
||
$this->docZen->initLibForTeamSpace();
|
||
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");
|
||
}
|
||
|
||
/**
|
||
* 设置选择文档库类型的范围。
|
||
* Set the scope of the document library type to be selected.
|
||
*
|
||
* @param string $objectType
|
||
* @param string $params
|
||
* @param string $from
|
||
* @access public
|
||
* @return void
|
||
*/
|
||
public function selectLibType($objectType = 'mine', $params = '', $from = '')
|
||
{
|
||
if($_POST)
|
||
{
|
||
$response = array();
|
||
|
||
$libID = $_POST['lib'];
|
||
$moduleID = $_POST['module'];
|
||
$rootSpace = $_POST['rootSpace'];
|
||
$docType = isset($_POST['type']) ? $_POST['type'] : 'doc';
|
||
if(empty($libID)) return $this->send(array('result' => 'fail', 'message' => sprintf($this->lang->error->notempty, $this->lang->doc->lib)));
|
||
|
||
$spaceID = 0;
|
||
if(in_array($rootSpace, array('mine', 'custom', 'product', 'project')))
|
||
{
|
||
$methodList = array('mine' => 'mySpace', 'custom' => 'teamSpace', 'product' => 'productSpace', 'project' => 'projectSpace');
|
||
$spaceID = $_POST[$rootSpace];
|
||
$method = $methodList[$rootSpace];
|
||
|
||
if($docType == 'doc') $url = $this->createLink('doc', $method, "objectID=$spaceID&libID=$libID&moduleID=$moduleID&browseType=all¶ms=0&orderBy=&recTotal=0&recPerPage=20&pageID=1&mode=create");
|
||
else $url = helper::createLink('api', 'create', "libID=$libID&moduleID=$moduleID&space=$rootSpace");
|
||
}
|
||
elseif($rootSpace == 'api')
|
||
{
|
||
$url = helper::createLink('api', 'create', "libID=$libID&moduleID=$moduleID&space=$rootSpace");
|
||
}
|
||
|
||
$response['result'] = 'success';
|
||
$response['closeModal'] = true;
|
||
$response['callback'] = "redirectParentWindow(\"{$url}\", \"{$from}\", \"{$spaceID}\", \"{$libID}\", \"{$moduleID}\")";
|
||
return $this->send($response);
|
||
}
|
||
|
||
$spaceList = $this->lang->doc->spaceList;
|
||
$typeList = $this->lang->doc->types;
|
||
if(!common::hasPriv('doc', 'create')) unset($spaceList['mine'], $spaceList['custom'], $typeList['doc']);
|
||
if(!common::hasPriv('doc', 'mySpace')) unset($spaceList['mine']);
|
||
if(!common::hasPriv('doc', 'productSpace')) unset($spaceList['product']);
|
||
if(!common::hasPriv('doc', 'projectSpace')) unset($spaceList['project']);
|
||
if(!common::hasPriv('doc', 'teamSpace')) unset($spaceList['custom']);
|
||
if(!common::hasPriv('api', 'index')) unset($spaceList['api']);
|
||
if(!common::hasPriv('api', 'create')) unset($spaceList['api'], $typeList['api']);
|
||
if($this->config->vision == 'lite') unset($spaceList['api'], $spaceList['product'], $typeList['api']);
|
||
|
||
$params = helper::safe64Decode($params);
|
||
parse_str($params, $params);
|
||
|
||
$this->view->params = $params;
|
||
$this->view->objectType = $objectType;
|
||
$this->view->spaceList = $spaceList;
|
||
$this->view->typeList = $typeList;
|
||
$this->view->from = $from;
|
||
|
||
$this->display();
|
||
}
|
||
|
||
/**
|
||
* Ajax: 根据对象类型设置下拉菜单。
|
||
* Ajax: Set the drop-down menu according to the object type.
|
||
*
|
||
* @param string $objectType product|project
|
||
* @param int $objectID
|
||
* @param string $module
|
||
* @param string $method
|
||
* @access public
|
||
* @return void
|
||
*/
|
||
public function ajaxGetDropMenu(string $objectType, int $objectID, string $module, string $method)
|
||
{
|
||
list($myObjects, $normalObjects, $closedObjects) = $this->doc->getOrderedObjects($objectType, 'nomerge', $objectID);
|
||
|
||
$libData = $this->doc->setMenuByType($objectType, $objectID, 0);
|
||
|
||
$this->view->objectType = $objectType;
|
||
$this->view->objectID = $objectID;
|
||
$this->view->libID = !empty($libData[1]) ? $libData[1] : 0;
|
||
$this->view->module = $module;
|
||
$this->view->method = $method == 'view' ? $objectType.'space' : $method;
|
||
$this->view->normalObjects = $myObjects + $normalObjects;
|
||
$this->view->closedObjects = $closedObjects;
|
||
$this->view->objectsPinYin = common::convert2Pinyin($myObjects + $normalObjects + $closedObjects);
|
||
|
||
$this->display();
|
||
}
|
||
|
||
/**
|
||
* Ajax: 获取空间的下拉数据。
|
||
* Ajax: Get the space drop down.
|
||
*
|
||
* @param int $libID
|
||
* @param string $module
|
||
* @param string $method
|
||
* @access public
|
||
* @return void
|
||
*/
|
||
public function ajaxGetSpaceMenu(int $libID, string $module, string $method, string $extra = 'nomine')
|
||
{
|
||
$this->view->libID = $libID;
|
||
$this->view->module = $module;
|
||
$this->view->method = $method;
|
||
$this->view->extra = $extra;
|
||
$this->view->spaces = $this->docZen->getAllSpaces($extra);
|
||
|
||
$this->display();
|
||
}
|
||
|
||
/**
|
||
* Ajax: 获取执行下拉数据。
|
||
* Ajax: Get the execution drop down by the projectID.
|
||
*
|
||
* @param int $projectID
|
||
* @access public
|
||
* @return string
|
||
*/
|
||
public function ajaxGetExecution(int $projectID)
|
||
{
|
||
$json = array();
|
||
$items = array();
|
||
|
||
$executionPairs = $this->execution->getPairs($projectID, 'all', 'multiple,leaf,noprefix');
|
||
foreach($executionPairs as $id => $name) $items[] = array('text' => $name, 'value' => $id, 'keys' => $name);
|
||
|
||
$json['items'] = $items;
|
||
$json['project'] = $this->project->getByID($projectID);
|
||
return print(json_encode($json));
|
||
}
|
||
|
||
/**
|
||
* 编辑一个目录。
|
||
* Edit a catalog.
|
||
*
|
||
* @param int $moduleID
|
||
* @param string $type doc|api
|
||
* @access public
|
||
* @return void
|
||
*/
|
||
public function editCatalog(int $moduleID, string $type)
|
||
{
|
||
echo $this->fetch('tree', 'edit', "moduleID={$moduleID}&type={$type}");
|
||
}
|
||
|
||
/**
|
||
* 删除一个目录。
|
||
* Delete a catalog.
|
||
*
|
||
* @param int $moduleID
|
||
* @access public
|
||
* @return void
|
||
*/
|
||
public function deleteCatalog(int $moduleID)
|
||
{
|
||
echo $this->fetch('tree', 'delete', "moduleID={$moduleID}&confirm=yes");
|
||
}
|
||
|
||
/**
|
||
* 设置左侧树中是否显示文档。
|
||
* Set documents are show or hidden in the left tree.
|
||
*
|
||
* @access public
|
||
* @return void
|
||
*/
|
||
public function displaySetting()
|
||
{
|
||
$this->loadModel('setting');
|
||
if($_POST)
|
||
{
|
||
$this->setting->setItem($this->app->user->account . '.doc.showDoc', $this->post->showDoc);
|
||
return $this->sendSuccess(array('load' => true, 'closeModal' => true));
|
||
}
|
||
|
||
$showDoc = $this->setting->getItem('owner=' . $this->app->user->account . '&module=doc&key=showDoc');
|
||
$this->view->showDoc = $showDoc === '0' ? '0' : '1';
|
||
|
||
$this->display();
|
||
}
|
||
|
||
/**
|
||
* 文档库排序
|
||
* Doclib sorting.
|
||
*
|
||
* @access public
|
||
* @return void
|
||
*/
|
||
public function sortDoclib()
|
||
{
|
||
if($_POST)
|
||
{
|
||
$orders = $_POST['orders'];
|
||
if(is_string($orders)) $orders = json_decode($orders, true);
|
||
|
||
foreach($orders as $id => $order) $this->doc->updateDoclibOrder($id, (int)$order);
|
||
|
||
if(dao::isError()) return $this->send(array('result' => 'fail', 'message' => dao::getError()));
|
||
return $this->send(array('result' => 'success', 'orders' => $orders));
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 文档排序
|
||
* Doc sorting.
|
||
*
|
||
* @access public
|
||
* @return void
|
||
*/
|
||
public function sortDoc()
|
||
{
|
||
if($_POST)
|
||
{
|
||
$orders = json_decode($this->post->orders, true);
|
||
asort($orders);
|
||
$orders = array_flip($orders);
|
||
|
||
/* Sort by sorted id list. */
|
||
$this->doc->updateDocOrder($orders);
|
||
|
||
if(dao::isError()) return $this->send(array('result' => 'fail', 'message' => dao::getError()));
|
||
return $this->send(array('result' => 'success'));
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 目录排序
|
||
* Catalog sorting.
|
||
*
|
||
* @access public
|
||
* @return void
|
||
*/
|
||
public function sortCatalog()
|
||
{
|
||
if($_POST)
|
||
{
|
||
$orders = $_POST['orders'];
|
||
$type = isset($_POST['type']) ? $_POST['type'] : 'doc';
|
||
if(is_string($orders)) $orders = json_decode($orders, true);
|
||
foreach($orders as $id => $order) $this->doc->updateOrder($id, (int)$order, $type);
|
||
|
||
if(dao::isError()) return $this->send(array('result' => 'fail', 'message' => dao::getError()));
|
||
return $this->send(array('result' => 'success'));
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 删除文档附件。
|
||
* Delete file for doc.
|
||
*
|
||
* @param int $docID
|
||
* @param int $fileID
|
||
* @param string $confirm
|
||
* @access public
|
||
* @return void
|
||
*/
|
||
public function deleteFile(int $docID, int $fileID, string $confirm = 'no')
|
||
{
|
||
$this->loadModel('file');
|
||
if($confirm == 'no')
|
||
{
|
||
$formUrl = inlink('deleteFile', "docID={$docID}&fileID={$fileID}&confirm=yes");
|
||
return $this->send(array('result' => 'fail', 'callback' => "zui.Modal.confirm('{$this->lang->file->confirmDelete}').then((res) => {if(res) $.ajaxSubmit({url: '$formUrl'});});"));
|
||
}
|
||
else
|
||
{
|
||
$this->doc->updateDocFile($docID, $fileID);
|
||
if(dao::isError()) return $this->send(array('result' => 'fail', 'message' => dao::getError()));
|
||
|
||
$file = $this->file->getById($fileID);
|
||
$this->action->create($file->objectType, $file->objectID, 'deletedFile', '', $file->title);
|
||
|
||
return $this->send(array('result' => 'success', 'message' => $this->lang->saveSuccess, 'load' => true));
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 移动文档库
|
||
* Move Lib.
|
||
*
|
||
* @param int $libID
|
||
* @param string $targetSpace [int]
|
||
* @access public
|
||
* @return void
|
||
*/
|
||
public function moveLib(int $libID, string $targetSpace = '')
|
||
{
|
||
$lib = $this->doc->getLibByID($libID);
|
||
if(empty($targetSpace)) $targetSpace = $this->doc->getLibTargetSpace($lib);
|
||
$spaceType = $this->doc->getParamFromTargetSpace($targetSpace, 'type');
|
||
|
||
if(!empty($lib->main)) return $this->send(array('result' => 'fail', 'message' => $this->lang->doc->errorEditSystemDoc));
|
||
|
||
if(!empty($_POST))
|
||
{
|
||
$data = form::data()
|
||
->setIF($this->post->acl == 'open', 'groups', '')
|
||
->setIF($this->post->acl == 'open', 'users', '')
|
||
->get();
|
||
if(dao::isError()) return $this->send(array('result' => 'fail', 'message' => dao::getError()));
|
||
|
||
$this->doc->moveLib($libID, $data);
|
||
if(dao::isError()) return $this->send(array('result' => 'fail', 'message' => dao::getError()));
|
||
$spaceTypeChanged = $spaceType != $lib->type;
|
||
return $this->docZen->responseAfterMove($this->post->space, $libID, 0, $spaceTypeChanged);
|
||
}
|
||
|
||
$this->docZen->setAclForCreateLib($spaceType);
|
||
|
||
$this->view->title = $this->lang->doc->moveLibAction;
|
||
$this->view->spaces = $this->doc->getAllSubSpaces('all');
|
||
$this->view->lib = $lib;
|
||
$this->view->targetSpace = $targetSpace;
|
||
$this->view->libType = $spaceType;
|
||
$this->view->hasOthersDoc = $this->doc->hasOthersDoc($lib);
|
||
$this->view->groups = $this->loadModel('group')->getPairs();
|
||
$this->view->users = $this->loadModel('user')->getPairs('nocode|noclosed');
|
||
$this->display();
|
||
}
|
||
|
||
/**
|
||
* 移动文档
|
||
* Move Document.
|
||
*
|
||
* @param int $docID
|
||
* @param int $libID
|
||
* @param string $spaceType
|
||
* @param string $space
|
||
* @access public
|
||
* @return void
|
||
*/
|
||
public function moveDoc(int $docID, int $libID = 0, string $spaceType = '', string $space = '')
|
||
{
|
||
if($spaceType == 'quick')
|
||
{
|
||
$libID = 0;
|
||
$space = $spaceType = '';
|
||
}
|
||
|
||
$doc = $this->doc->getByID($docID);
|
||
if(empty($libID)) $libID = (int)$doc->lib;
|
||
$lib = $this->doc->getLibByID($libID);
|
||
|
||
if(empty($space))
|
||
{
|
||
if($lib->parent)
|
||
{
|
||
$space = $lib->parent;
|
||
}
|
||
else
|
||
{
|
||
if($lib->product) $space = $lib->product;
|
||
if($lib->project) $space = $lib->project;
|
||
}
|
||
}
|
||
|
||
if(empty($spaceType))
|
||
{
|
||
if($lib->parent)
|
||
{
|
||
$spaceType = $this->doc->getSpaceType($space);
|
||
}
|
||
else
|
||
{
|
||
if($lib->product && $lib->type == 'product') $spaceType = 'product';
|
||
if($lib->project && $lib->type == 'project') $spaceType = 'project';
|
||
}
|
||
}
|
||
|
||
if(!empty($_POST))
|
||
{
|
||
/* parent带‘m_’前缀为目录。*/
|
||
if(isset($_POST['parent']) && strpos($_POST['parent'], 'm_') !== false)
|
||
{
|
||
$_POST['module'] = str_replace('m_', '', $_POST['parent']);
|
||
$_POST['parent'] = 0;
|
||
}
|
||
|
||
$data = form::data()
|
||
->setIF($this->post->acl == 'open', 'groups', '')
|
||
->setIF($this->post->acl == 'open', 'users', '')
|
||
->setIF($this->post->acl == 'open', 'readGroups', '')
|
||
->setIF($this->post->acl == 'open', 'readUsers', '')
|
||
->setIF(in_array($spaceType, array('project', 'product')), $spaceType, $space)
|
||
->setIF($spaceType != 'project', 'project', 0)
|
||
->setIF($spaceType != 'product', 'product', 0)
|
||
->get();
|
||
if(dao::isError()) return $this->send(array('result' => 'fail', 'message' => dao::getError()));
|
||
|
||
$changes = common::createChanges($doc, $data);
|
||
if($changes)
|
||
{
|
||
$this->doc->doUpdateDoc($docID, $data);
|
||
if(dao::isError()) return $this->send(array('result' => 'fail', 'message' => dao::getError()));
|
||
|
||
$actionID = $this->loadModel('action')->create('doc', $docID, 'Moved', '', json_encode(array('from' => $doc->lib, 'to' => $data->lib)));
|
||
$this->action->logHistory($actionID, $changes);
|
||
}
|
||
|
||
$spaceTypeChanged = $spaceType != $lib->type;
|
||
return $this->docZen->responseAfterMove($this->post->space, $data->lib, $docID, $spaceTypeChanged);
|
||
}
|
||
|
||
$projects = $this->loadModel('project')->getPairsByProgram(0, 'all', false, 'order_asc');
|
||
$products = $this->loadModel('product')->getPairs();
|
||
$executions = $this->loadModel('execution')->getPairs(0, 'all', 'multiple,leaf');
|
||
|
||
$libPairs = $this->doc->getLibPairs($spaceType, 'withObject', (int)$space, '', $products, $projects, $executions);
|
||
if($spaceType == 'project') $libPairs += $this->doc->getExecutionLibPairsByProject((int)$space, 'withObject', $executions);
|
||
|
||
if(!isset($libPairs[$libID])) $libID = (int)key($libPairs);
|
||
|
||
$chapterAndDocs = $this->doc->getDocsOfLibs(array($libID), $spaceType, $docID);
|
||
$modulePairs = empty($libID) ? array() : $this->loadModel('tree')->getOptionMenu($libID, 'doc', 0);
|
||
if(isset($doc) && !empty($doc->parent) && !isset($chapterAndDocs[$doc->parent])) $chapterAndDocs[$doc->parent] = $this->doc->fetchByID($doc->parent);
|
||
$chapterAndDocs = $this->doc->buildNestedDocs($chapterAndDocs, $modulePairs);
|
||
|
||
$this->view->docID = $docID;
|
||
$this->view->libID = $libID;
|
||
$this->view->spaceType = $spaceType;
|
||
$this->view->space = $space;
|
||
$this->view->doc = $doc;
|
||
$this->view->spaces = $this->doc->getAllSubSpaces($this->app->tab != 'doc' ? $this->app->tab : 'all');
|
||
$this->view->libPairs = $libPairs;
|
||
$this->view->optionMenu = $chapterAndDocs;
|
||
$this->view->groups = $this->loadModel('group')->getPairs();
|
||
$this->view->users = $this->loadModel('user')->getPairs('nocode|noclosed');
|
||
$this->display();
|
||
}
|
||
|
||
/**
|
||
* 移动文档模板
|
||
* Move document template.
|
||
*
|
||
* @param int $docID
|
||
* @access public
|
||
* @return void
|
||
*/
|
||
public function moveTemplate(int $docID)
|
||
{
|
||
$doc = $this->doc->getByID($docID);
|
||
if(!empty($_POST))
|
||
{
|
||
$this->lang->doc->module = $this->lang->docTemplate->module;
|
||
$data = form::data()
|
||
->setIF(!isset($_POST['lib']), 'lib', $doc->lib)
|
||
->setIF(!isset($_POST['module']), 'module', $doc->module)
|
||
->setIF(!isset($_POST['parent']), 'parent', $doc->parent)
|
||
->setIF(!isset($_POST['acl']), 'acl', $doc->acl)
|
||
->get();
|
||
$changes = common::createChanges($doc, $data);
|
||
if($changes)
|
||
{
|
||
$basicInfoChanged = false;
|
||
foreach($changes as $change)
|
||
{
|
||
if(in_array($change['field'], array('module', 'lib', 'acl'))) $basicInfoChanged = true;
|
||
}
|
||
$this->doc->doUpdateDoc($docID, $data, $basicInfoChanged);
|
||
if(dao::isError()) return $this->send(array('result' => 'fail', 'message' => dao::getError()));
|
||
|
||
$actionID = $this->loadModel('action')->create('docTemplate', $docID, 'Moved', '', json_encode(array('from' => $doc->lib, 'to' => $data->lib)));
|
||
$this->action->logHistory($actionID, $changes);
|
||
}
|
||
|
||
$newDoc = $this->doc->getByID($docID);
|
||
if(!$this->doc->checkPrivDoc($newDoc))
|
||
{
|
||
$link = $this->createLink('doc', 'browseTemplate', "libID={$doc->lib}&type=all&docID=0&orderBy=id_desc&recPerPage=20&pageID=1&mode=list");
|
||
return $this->send(array('result' => 'success', 'message' => $this->lang->saveSuccess, 'load' => $link, 'doc' => $newDoc));
|
||
}
|
||
|
||
$docAppAction = array('executeCommand', 'handleMovedDoc', array($docID, '1', $data->lib));
|
||
return $this->send(array('result' => 'success', 'message' => $this->lang->saveSuccess, 'closeModal' => true, 'docApp' => $docAppAction));
|
||
}
|
||
|
||
if(!empty($doc->parent))
|
||
{
|
||
$parentDoc = $this->doc->fetchByID($doc->parent);
|
||
$chapterAndDocs = $this->doc->getDocsOfLibs(array($doc->lib), 'template', $docID, true);
|
||
if(!isset($chapterAndDocs[$doc->parent])) $chapterAndDocs[$doc->parent] = $parentDoc;
|
||
|
||
$parentPath = trim($parentDoc->path, ',') . ",";
|
||
$topTemplate = substr($parentPath, 0, strpos($parentPath, ',')) ?: $doc->parent;
|
||
foreach($chapterAndDocs as $key => $template)
|
||
{
|
||
if(strpos(",{$template->path},", ",{$topTemplate},") === false) unset($chapterAndDocs[$key]);
|
||
}
|
||
$this->view->chapterAndDocs = $this->doc->buildNestedDocs($chapterAndDocs);
|
||
}
|
||
|
||
$scopeList = $this->doc->getTemplateScopes();
|
||
|
||
$this->view->scopeItems = $this->doc->getScopeItems($scopeList);
|
||
$this->view->doc = $doc;
|
||
$this->view->docID = $docID;
|
||
$this->view->modules = $this->loadModel('tree')->getOptionMenu((int)$doc->lib, 'docTemplate', 0, 'all', 'nodeleted', 'all');
|
||
$this->display();
|
||
}
|
||
|
||
/**
|
||
* Batch move document.
|
||
*
|
||
* @param string $type
|
||
* @param string $encodeDocIdList
|
||
* @param int $spaceID
|
||
* @param int $libID
|
||
* @param int $moduleID
|
||
* @access public
|
||
* @return void
|
||
*/
|
||
public function batchMoveDoc(string $type, string $encodeDocIdList, int $spaceID, int $libID = 0, int $moduleID = 0)
|
||
{
|
||
$docIdList = json_decode(base64_decode($encodeDocIdList), true);
|
||
if(!$docIdList) $this->locate($this->createLink('doc', 'app', "type={$type}&spaceID={$spaceID}&libID={$libID}&moduleID={$moduleID}"));
|
||
|
||
$spaces = $this->doc->getAllSubSpaces();
|
||
if($type == 'quick')
|
||
{
|
||
list($type, $spaceID) = explode('.', key($spaces));
|
||
$spaceID = (int) $spaceID;
|
||
}
|
||
|
||
if($_POST)
|
||
{
|
||
$oldDocList = $this->doc->getDocsByIdList($docIdList);
|
||
|
||
$data = form::data()
|
||
->setIF($type == 'mine' || $this->post->acl == 'open', 'groups', '')
|
||
->setIF($type == 'mine' || $this->post->acl == 'open', 'users', '')
|
||
->setIF(in_array($type, array('project', 'product')), $type, $spaceID)
|
||
->get();
|
||
$this->doc->batchMoveDoc($data, $docIdList);
|
||
|
||
if(dao::isError()) return $this->send(array('result' => 'fail', 'message' => dao::getError()));
|
||
|
||
$this->docZen->recordBatchMoveActions($oldDocList, $data);
|
||
|
||
return $this->send(array('result' => 'success', 'message' => $this->lang->saveSuccess, 'closeModal' => true, 'docApp' => array('load', null, null, null, array('noLoading' => true, 'picks' => 'doc'))));
|
||
}
|
||
|
||
$projects = $this->loadModel('project')->getPairsByProgram(0, 'all', false, 'order_asc');
|
||
$products = $this->loadModel('product')->getPairs();
|
||
$executions = $this->loadModel('execution')->getPairs(0, 'all', 'multiple,leaf');
|
||
|
||
$libPairs = $this->doc->getLibPairs($type, 'withObject', $spaceID, '', $products, $projects, $executions);
|
||
if($type == 'project') $libPairs += $this->doc->getExecutionLibPairsByProject($spaceID, 'withObject', $executions);
|
||
|
||
if(!isset($libPairs[$libID])) $libID = (int)key($libPairs);
|
||
|
||
$docList = $this->doc->getByIdList($docIdList);
|
||
$docAclList = array_column($docList, 'acl');
|
||
|
||
$this->view->title = $this->lang->doc->batchMove;
|
||
$this->view->encodeDocIdList = $encodeDocIdList;
|
||
$this->view->type = $type;
|
||
$this->view->spaceID = $spaceID;
|
||
$this->view->libID = $libID;
|
||
$this->view->moduleID = $moduleID;
|
||
$this->view->spaces = $spaces;
|
||
$this->view->libPairs = $libPairs;
|
||
$this->view->optionMenu = $this->loadModel('tree')->getOptionMenu($libID, 'doc', 0);
|
||
$this->view->groups = $this->loadModel('group')->getPairs();
|
||
$this->view->users = $this->loadModel('user')->getPairs('nocode|noclosed');
|
||
$this->view->hasOpenDoc = in_array('open', $docAclList);
|
||
$this->display();
|
||
}
|
||
|
||
/**
|
||
* Ajax: 检查对象权限。
|
||
* Ajax check object priv.
|
||
*
|
||
* @param string $objectType
|
||
* @param int $objectID
|
||
* @access public
|
||
* @return void
|
||
*/
|
||
public function ajaxCheckObjectPriv(string $objectType, int $objectID)
|
||
{
|
||
$accounts = $this->post->users;
|
||
$object = $this->doc->getObjectByID($objectType, $objectID);
|
||
if(empty($object)) return print('');
|
||
if($object->acl == 'open') return print('');
|
||
|
||
$this->loadModel('user');
|
||
$userViews = $this->dao->select('*')->from(TABLE_USERVIEW)->where('account')->in($accounts)->fetchAll('account');
|
||
$userPairs = $this->dao->select('account,realname')->from(TABLE_USER)->where('account')->in($accounts)->fetchPairs('account', 'realname');
|
||
$denyUsers = array();
|
||
foreach($accounts as $account)
|
||
{
|
||
if(strpos(",{$this->app->company->admins}", ",{$account},") !== false) continue;
|
||
|
||
$userView = zget($userViews, $account, '');
|
||
if(empty($userView)) $userView = $this->user->computeUserView($account, true);
|
||
|
||
if($objectType == 'product' && isset($userView->products) && strpos(",{$userView->products},", ",{$objectID},") === false) $denyUsers[$account] = zget($userPairs, $account);
|
||
if($objectType == 'project' && isset($userView->projects) && strpos(",{$userView->projects},", ",{$objectID},") === false) $denyUsers[$account] = zget($userPairs, $account);
|
||
if($objectType == 'execution' && isset($userView->sprints) && strpos(",{$userView->sprints},", ",{$objectID},") === false) $denyUsers[$account] = zget($userPairs, $account);
|
||
}
|
||
|
||
if(empty($denyUsers)) return print('');
|
||
if(isset($this->lang->doc->whitelistDeny[$objectType])) return printf($this->lang->doc->whitelistDeny[$objectType], implode('、', $denyUsers));
|
||
}
|
||
|
||
/**
|
||
* Ajax: 检查库权限。
|
||
* Ajax check lib priv.
|
||
*
|
||
* @param int $libID
|
||
* @access public
|
||
* @return void
|
||
*/
|
||
public function ajaxCheckLibPriv(int $libID)
|
||
{
|
||
$accounts = $this->post->users;
|
||
$lib = $this->doc->getLibByID($libID);
|
||
if(empty($lib)) return print('');
|
||
if($lib->acl == 'open') return print('');
|
||
if($lib->acl == 'default' && strpos("product,project,execution", $lib->type) !== false) return $this->ajaxCheckObjectPriv($lib->type, zget($lib, $lib->type, 0));
|
||
|
||
$authAccounts[$lib->addedBy] = $lib->addedBy;
|
||
if($lib->groups) $authAccounts += $this->loadModel('group')->getGroupAccounts(explode(',', $lib->groups));
|
||
if($lib->users)
|
||
{
|
||
foreach(array_filter(explode(',', $lib->users)) as $account) $authAccounts[$account] = $account;
|
||
}
|
||
|
||
$userPairs = $this->dao->select('account,realname')->from(TABLE_USER)->where('account')->in($accounts)->fetchPairs('account', 'realname');
|
||
$denyUsers = array();
|
||
foreach($accounts as $account)
|
||
{
|
||
if(strpos(",{$this->app->company->admins}", ",{$account},") !== false) continue;
|
||
if(!isset($authAccounts[$account])) $denyUsers[$account] = zget($userPairs, $account);
|
||
}
|
||
|
||
if(empty($denyUsers)) return print('');
|
||
if(isset($this->lang->doc->whitelistDeny['doc'])) return printf($this->lang->doc->whitelistDeny['doc'], implode('、', $denyUsers));
|
||
}
|
||
|
||
/**
|
||
* Doc app view.
|
||
* 文档应用视图。
|
||
*
|
||
* @param string $type
|
||
* @param int $spaceID
|
||
* @param int $libID
|
||
* @param int $moduleID
|
||
* @param mixed $docID
|
||
* @param string $mode
|
||
* @param string $orderBy
|
||
* @param int $recTotal
|
||
* @param int $recPerPage
|
||
* @param int $pageID
|
||
* @param string $filterType
|
||
* @param string $search
|
||
* @param string $param
|
||
* @access public
|
||
* @access public
|
||
* @return void
|
||
*/
|
||
public function app(string $type = 'mine', int $spaceID = 0, int $libID = 0, int $moduleID = 0, mixed $docID = 0, string $mode = '', string $orderBy = '', int $recTotal = 0, int $recPerPage = 20, int $pageID = 1, string $filterType = '', string $search = '', bool $noSpace = false)
|
||
{
|
||
$isNotDocTab = $this->app->tab != 'doc';
|
||
if(empty($mode))
|
||
{
|
||
$showList = $noSpace || !empty($spaceID);
|
||
$mode = ($isNotDocTab || $type == 'execution' || $showList) ? 'list' : 'home';
|
||
}
|
||
|
||
$this->app->loadLang('file');
|
||
|
||
/* For product drop menu. */
|
||
if(!$isNotDocTab && $type == 'execution')
|
||
{
|
||
$execution = $this->loadModel('execution')->getByID($spaceID);
|
||
$type = 'project';
|
||
$spaceID = $execution->project;
|
||
}
|
||
if($isNotDocTab && in_array($type, array('product', 'project', 'execution')))
|
||
{
|
||
if($type == 'product' && $spaceID == 0) $spaceID = (int)$this->cookie->preProductID;
|
||
$this->doc->setMenuByType($type, $spaceID, $libID);
|
||
$objectKey = $type . 'ID';
|
||
$this->view->$objectKey = $spaceID;
|
||
$this->view->$type = $this->doc->fetchByID($spaceID, $type);
|
||
}
|
||
|
||
if($type == 'mine') $menuType = 'my';
|
||
else $menuType = $type == 'custom' ? 'team' : $type;
|
||
if(isset($this->lang->doc->menu->{$menuType})) $this->lang->doc->menu->{$menuType}['alias'] .= ',' . $this->app->rawMethod;
|
||
|
||
$docVersion = 0;
|
||
$isApi = is_string($docID) && strpos($docID, 'api.') === 0;
|
||
if($isApi) $docID = str_replace('api.', '', $docID);
|
||
if(is_string($docID) && strpos($docID, '_') !== false) list($docID, $docVersion) = explode('_', $docID);
|
||
|
||
$this->view->type = $type;
|
||
$this->view->spaceID = $spaceID;
|
||
$this->view->libID = $libID;
|
||
$this->view->moduleID = $moduleID;
|
||
$this->view->docID = $isApi ? "api.$docID" : (int)$docID;
|
||
$this->view->docVersion = (int)$docVersion;
|
||
$this->view->mode = $mode;
|
||
$this->view->filterType = $filterType;
|
||
$this->view->search = $search;
|
||
$this->view->recTotal = $recTotal;
|
||
$this->view->recPerPage = $recPerPage;
|
||
$this->view->pageID = $pageID;
|
||
$this->view->orderBy = $orderBy;
|
||
$this->view->objectType = $type;
|
||
$this->view->noSpace = $noSpace;
|
||
$this->view->objectID = $spaceID;
|
||
$this->view->users = $this->dao->select('account,realname,avatar')->from(TABLE_USER)->where('deleted')->eq('0')->fetchAll('account');
|
||
$this->view->title = isset($this->lang->doc->spaceList[$type]) ? $this->lang->doc->spaceList[$type] : $this->lang->doc->common;
|
||
$this->display();
|
||
}
|
||
|
||
/**
|
||
* Doc quick access page.
|
||
* 快捷访问页面。
|
||
*
|
||
* @param string $type 'view'|'collect'|'createdby'|'editedby'
|
||
* @param int $docID
|
||
* @param string $orderBy
|
||
* @param int $recPerPage
|
||
* @param int $pageID
|
||
* @access public
|
||
* @return void
|
||
*/
|
||
public function quick(string $type = 'view', int $docID = 0, string $orderBy = '', int $recPerPage = 20, int $pageID = 1)
|
||
{
|
||
if(empty($orderBy)) $orderBy = 'id_desc';
|
||
if(!isset($this->config->doc->quickMenu[$type])) $type = 'view';
|
||
$menu = $this->config->doc->quickMenu[$type];
|
||
|
||
$currentUser = $this->app->user->account;
|
||
$docs = $this->doc->getMineList($type, 'all', 0, $orderBy);
|
||
$order = 0;
|
||
foreach($docs as $doc)
|
||
{
|
||
$order++;
|
||
unset($doc->draft);
|
||
$doc->originLIb = $doc->lib;
|
||
$doc->lib = $menu['id'];
|
||
$doc->order = $order;
|
||
$doc->isCollector = strpos($doc->collector, ',' . $currentUser . ',') !== false;
|
||
}
|
||
|
||
$this->view->docs = $docs;
|
||
$this->view->menu = $menu;
|
||
$this->view->type = $type;
|
||
$this->view->docID = $docID;
|
||
$this->view->orderBy = $orderBy;
|
||
$this->view->recPerPage = $recPerPage;
|
||
$this->view->pageID = $pageID;
|
||
$this->view->users = $this->dao->select('account,realname,avatar')->from(TABLE_USER)->where('deleted')->eq('0')->fetchAll('account');
|
||
$this->view->title = $this->lang->doc->quick;
|
||
$this->display();
|
||
}
|
||
|
||
/**
|
||
* Ajax: Get doc space data.
|
||
* Ajax: 获取文档空间数据。
|
||
*
|
||
* @param string $type
|
||
* @param int $space
|
||
* @access public
|
||
* @return void
|
||
*/
|
||
public function ajaxGetSpaceData(string $type = 'custom', int $spaceID = 0, string $picks = '', int $libID = 0)
|
||
{
|
||
$this->doc->setMenuByType($type, (int)$spaceID, 0);
|
||
|
||
if($type === 'template')
|
||
{
|
||
$modules = $this->doc->getTemplateModules();
|
||
$moduleNames = array_column($modules, 'fullName', 'id');
|
||
$templateList = $this->doc->getDocTemplateList(0, 'all');
|
||
$templateList = $this->doc->filterDeletedDocs($templateList);
|
||
$templateList = $this->doc->filterPrivDocs($templateList, 'template');
|
||
foreach($templateList as $template)
|
||
{
|
||
$template->moduleName = zget($moduleNames, $template->module);
|
||
}
|
||
$data = array('spaceID' => $spaceID, 'docs' => array_values($templateList));
|
||
$data['spaces'][] = array('name' => $this->lang->doc->template, 'id' => $spaceID);
|
||
$data['modules'] = $modules;
|
||
|
||
$scopeList = $this->doc->getTemplateScopes();
|
||
foreach($scopeList as $scope) $data['libs'][] = array('id' => $scope->id, 'name' => $scope->name, 'space' => $spaceID);
|
||
}
|
||
else
|
||
{
|
||
$noPicks = empty($picks);
|
||
$picks = $noPicks ? '' : ",$picks,";
|
||
|
||
list($spaces, $spaceID) = $this->doc->getSpaces($type, $spaceID);
|
||
$data = array('spaceID' => (int)$spaceID);
|
||
$libs = $this->doc->getLibsOfSpace($type, $spaceID);
|
||
$libIds = array_keys($libs);
|
||
foreach($libs as $lib) $lib->order = (int)$lib->order;
|
||
|
||
if($noPicks || strpos($picks, ',space,') !== false) $data['spaces'] = $spaces;
|
||
if($noPicks || strpos($picks, ',lib,') !== false) $data['libs'] = array_values($libs);
|
||
if($noPicks || strpos($picks, ',module,') !== false) $data['modules'] = array_values($this->doc->getModulesOfLibs($libIds));
|
||
if($noPicks || strpos($picks, ',doc,') !== false) $data['docs'] = array_values($this->doc->getDocsOfLibs($libIds + array($spaceID), $type));
|
||
}
|
||
|
||
$this->send($data);
|
||
}
|
||
|
||
/**
|
||
* Ajax: Get doc data.
|
||
* Ajax: 获取文档数据。
|
||
*
|
||
* @param string|int $docID
|
||
* @param int $version
|
||
* @access public
|
||
* @return void
|
||
*/
|
||
public function ajaxGetDoc(string|int $docID, int $version = 0, $details = 'no')
|
||
{
|
||
if(is_string($docID) && strpos($docID, 'api.') === 0)
|
||
{
|
||
$apiID = (int)str_replace('api.', '', $docID);
|
||
echo $this->fetch('api', 'ajaxGetApi', "apiID=$apiID&version=$version");
|
||
return;
|
||
}
|
||
|
||
$docID = (int)$docID;
|
||
$doc = $this->doc->getByID($docID, $version);
|
||
$doc->lib = (int)$doc->lib;
|
||
$doc->module = (int)$doc->module;
|
||
$doc->privs = array('edit' => common::hasPriv('doc', 'edit', $doc) && $doc->acl == 'open');
|
||
$doc->editors = $this->doc->getEditors($docID);
|
||
$doc->draft = $doc->status == 'draft' ? $this->doc->getContent($docID, 0) : null;
|
||
|
||
$lib = $this->doc->getLibByID((int)$doc->lib);
|
||
$objectType = $lib->type;
|
||
if(empty($objectType))
|
||
{
|
||
if($lib->execution) $objectType = 'execution';
|
||
elseif($lib->project) $objectType = 'project';
|
||
elseif($lib->product) $objectType = 'product';
|
||
}
|
||
|
||
$this->doc->setDocPriv($doc, $objectType);
|
||
|
||
if($details == 'yes')
|
||
{
|
||
$objectID = $this->doc->getObjectIDByLib($lib, $objectType);
|
||
$object = in_array($objectType, array('product', 'project', 'execution')) ? $this->doc->getObjectByID($objectType, $objectID) : $this->doc->getLibByID((int)$objectID);
|
||
|
||
$doc->libInfo = $lib;
|
||
$doc->objectType = $objectType;
|
||
$doc->object = $object;
|
||
}
|
||
|
||
if(!empty($doc->rawContent))
|
||
{
|
||
$doc->html = $doc->content;
|
||
$doc->content = $doc->rawContent;
|
||
unset($doc->rawContent);
|
||
|
||
if(empty($doc->templateType) && $doc->contentType == 'doc' && preg_match('/ src="{([0-9]+)(\.(\w+))?}" /', $doc->html))
|
||
{
|
||
$doc->contentType = 'html';
|
||
$doc->content = preg_replace('/ src="{([0-9]+)(\.(\w+))?}" /', ' src="' . helper::createLink('file', 'read', "fileID=$1", "$3") . '" ', $doc->html);
|
||
}
|
||
}
|
||
if($docID) $this->doc->createAction($docID, 'view');
|
||
|
||
$this->send($doc);
|
||
}
|
||
|
||
/**
|
||
* Get files by type and objectID.
|
||
* 根据类型和对象ID获取文件列表。
|
||
*
|
||
* @param string $type
|
||
* @param int $objectID
|
||
* @param string $browseType
|
||
* @param string $orderBy
|
||
* @param int $recTotal
|
||
* @param int $recPerPage
|
||
* @param int $pageID
|
||
* @access public
|
||
* @return void
|
||
*/
|
||
public function ajaxGetFiles(string $type, int $objectID, string $browseType = '', string $orderBy = 'id_desc', int $recTotal = 0, int $recPerPage = 9999, int $pageID = 1)
|
||
{
|
||
if(common::hasPriv('doc', 'showFiles'))
|
||
{
|
||
/* Load pager. */
|
||
$rawMethod = $this->app->rawMethod;
|
||
$this->app->rawMethod = 'showFiles';
|
||
$this->app->loadClass('pager', true);
|
||
$pager = new pager($recTotal, $recPerPage, $pageID);
|
||
$this->app->rawMethod = $rawMethod;
|
||
|
||
$files = $this->doc->getLibFiles($type, $objectID, $browseType, 0, $orderBy, $pager);
|
||
$sourcePairs = $this->doc->getFileSourcePairs($files);
|
||
$files = $this->docZen->processFiles($files, array(), $sourcePairs, true);
|
||
|
||
echo json_encode(array_values($files)); // $this->send($files); not work.
|
||
}
|
||
else
|
||
{
|
||
echo '[]';
|
||
}
|
||
}
|
||
|
||
/**
|
||
* Get lib summaries by space type and space list.
|
||
*
|
||
* @param string $spaceType
|
||
* @param string $spaceList
|
||
* @access public
|
||
* @return void
|
||
*/
|
||
public function ajaxGetLibSummaries(string $spaceType, string $spaceList)
|
||
{
|
||
$libsMap = $this->doc->getLibsOfSpaces($spaceType, $spaceList, 0);
|
||
echo json_encode($libsMap);
|
||
}
|
||
|
||
/**
|
||
* Ajax modal for setting doc basic info.
|
||
* 设置文档基本信息的模态框。
|
||
*
|
||
* @param string $objectType
|
||
* @param int $objectID
|
||
* @param int $libID
|
||
* @param int $moduleID
|
||
* @param int $docID
|
||
* @param string $isDraft
|
||
* @access public
|
||
*/
|
||
public function setDocBasic(string $objectType, int $objectID, int $libID = 0, int $moduleID = 0, int $parentID = 0, int $docID = 0, string $isDraft = 'no', string $modalType = 'doc')
|
||
{
|
||
$this->doc->setMenuByType($objectType, (int)$objectID, (int)$libID);
|
||
$lib = $libID ? $this->doc->getLibByID($libID) : '';
|
||
$isCreate = empty($docID);
|
||
|
||
if($docID) $doc = $this->doc->getByID($docID);
|
||
|
||
$title = $this->lang->settings;
|
||
if($modalType == 'doc')
|
||
{
|
||
$title = $parentID ? $this->lang->doc->addSubDoc : $this->lang->doc->create;
|
||
if($objectType == 'template') $title = $parentID ? $this->lang->docTemplate->addSubDocTemplate : $this->lang->docTemplate->create;
|
||
if($isDraft == 'no') $title = $this->lang->settings;
|
||
}
|
||
if($modalType == 'chapter') $title = $isCreate ? $this->lang->doc->addChapter : $this->lang->doc->editChapter;
|
||
|
||
if($isCreate)
|
||
{
|
||
if(!$moduleID && $docID)
|
||
{
|
||
$parentDoc = $this->doc->getByID($parentID);
|
||
$moduleID = $parentDoc->module;
|
||
}
|
||
|
||
if(empty($objectID) && $lib) $objectID = $this->doc->getObjectIDByLib($lib);
|
||
if($lib && $objectType != 'template') $objectType = $lib->type;
|
||
|
||
$unclosed = strpos($this->config->doc->custom->showLibs, 'unclosed') !== false ? 'unclosedProject' : '';
|
||
$libPairs = $this->doc->getLibs($objectType, "{$unclosed}", $libID, $objectID);
|
||
$moduleID = $moduleID ? (int)$moduleID : (int)$this->cookie->lastDocModule;
|
||
if(!$libID && !empty($libPairs)) $libID = key($libPairs);
|
||
if(empty($lib) && $libID) $lib = $this->doc->getLibByID($libID);
|
||
|
||
if($objectType == 'custom' || $objectType == 'mine') $this->view->spaces = $this->doc->getSubSpacesByType($objectType, true);
|
||
$this->docZen->setObjectsForCreate($objectType, empty($lib) ? null : $lib, $unclosed, $objectID);
|
||
$this->view->optionMenu = empty($libID) ? array() : $this->loadModel('tree')->getOptionMenu($libID, 'doc', 0);
|
||
}
|
||
else
|
||
{
|
||
$parentID = (int)$doc->parent;
|
||
$moduleID = (int)$doc->module;
|
||
$libID = (int)$doc->lib;
|
||
$lib = $this->doc->getLibByID($libID);
|
||
if($lib && $objectType != 'template') $objectType = $lib->type;
|
||
$objectID = $this->doc->getObjectIDByLib($lib);
|
||
|
||
$libPairs = $this->doc->getLibs($objectType, '', $libID, $objectID);
|
||
if($objectType == 'custom' || $objectType == 'mine') $this->view->spaces = $this->doc->getSubSpacesByType($objectType, true);
|
||
$this->docZen->setObjectsForEdit($objectType, $objectID);
|
||
|
||
$this->view->doc = $doc;
|
||
$this->view->optionMenu = $this->loadModel('tree')->getOptionMenu($libID, 'doc', 0);
|
||
}
|
||
|
||
$chapterAndDocs = $this->doc->getDocsOfLibs(array($libID), $objectType, $docID, $objectType == 'template' ? true : false);
|
||
if($objectType == 'template' && !empty($moduleID)) $chapterAndDocs = array_filter($chapterAndDocs, fn($docInfo) => $docInfo->module == $moduleID);
|
||
if(isset($doc) && !empty($doc->parent) && !isset($chapterAndDocs[$doc->parent])) $chapterAndDocs[$doc->parent] = $this->doc->fetchByID($doc->parent);
|
||
$modulePairs = empty($libID) || $modalType == 'chapter' || $objectType == 'template' ? array() : $this->loadModel('tree')->getOptionMenu($libID, 'doc', 0);
|
||
|
||
if($objectType == 'template' && !empty($parentID))
|
||
{
|
||
$parentDoc = $this->doc->fetchByID($parentID);
|
||
$parentPath = trim($parentDoc->path, ',') . ",";
|
||
$topTemplate = substr($parentPath, 0, strpos($parentPath, ',')) ?: $parentID;
|
||
foreach($chapterAndDocs as $key => $template)
|
||
{
|
||
if(strpos(",{$template->path},", ",{$topTemplate},") === false) unset($chapterAndDocs[$key]);
|
||
}
|
||
}
|
||
$this->view->chapterAndDocs = $this->doc->buildNestedDocs($chapterAndDocs, $modulePairs);
|
||
|
||
if($objectType == 'template')
|
||
{
|
||
$scopeList = $this->doc->getTemplateScopes();
|
||
$this->view->scopeItems = $this->doc->getScopeItems($scopeList);
|
||
}
|
||
else
|
||
{
|
||
$this->view->users = $this->user->getPairs('nocode|noclosed|nodeleted');
|
||
$this->view->groups = $this->loadModel('group')->getPairs();
|
||
}
|
||
|
||
$docTitle = '';
|
||
if(!empty($doc))
|
||
{
|
||
$docTitle = $doc->title;
|
||
}
|
||
elseif($this->post->title)
|
||
{
|
||
$docTitle = $this->post->title;
|
||
}
|
||
|
||
$this->view->docID = $docID;
|
||
$this->view->docTitle = $docTitle;
|
||
$this->view->mode = empty($docID) ? 'create' : 'edit';
|
||
$this->view->libID = $libID;
|
||
$this->view->moduleID = $moduleID;
|
||
$this->view->objectID = $objectID;
|
||
$this->view->objectType = $objectType;
|
||
$this->view->lib = $lib;
|
||
$this->view->libs = $libPairs;
|
||
$this->view->parentID = $parentID;
|
||
$this->view->isDraft = $isDraft == 'yes';
|
||
$this->view->title = $title;
|
||
$this->view->modalType = $modalType;
|
||
$this->view->isCreate = $isCreate;
|
||
$this->display();
|
||
}
|
||
|
||
/**
|
||
* AJAX: 通过文档ID获取Confluence子文档。
|
||
* AJAX: Get confluence subdocuments by doc ID.
|
||
*
|
||
* @param int $originPageID 当前Confluence文档ID
|
||
* @param string $title 选择的父页面标题
|
||
* @param int $level 展示层级
|
||
* @access public
|
||
* @return void
|
||
*/
|
||
public function ajaxGetConfluenceChildren(int $originPageID, string $title, int $level = PHP_INT_MAX)
|
||
{
|
||
$parentID = $this->doc->getDocIdByTitle($originPageID, $title);
|
||
if(dao::isError()) return $this->send(array('result' => 'fail', 'message' => dao::getError()));
|
||
|
||
$docs = $this->docZen->getDocChildrenByRecursion((int)$parentID, $level);
|
||
if(dao::isError()) return $this->send(array('result' => 'fail', 'message' => dao::getError()));
|
||
|
||
return $this->send(array('result' => 'success', 'data' => $docs));
|
||
}
|
||
|
||
/**
|
||
* Ajax: Retrieve corresponding user information in the Zen path through Confluence user ID.
|
||
* Ajax: 通过Confluence用户ID获取在禅道中的对应用户信息。
|
||
*
|
||
* @param string $username
|
||
* @access public
|
||
* @return void
|
||
*/
|
||
public function ajaxGetConfluenceUser(string $username)
|
||
{
|
||
$user = $this->doc->getUserByConfluenceUserID($username);
|
||
return $this->send(array('result' => 'success', 'data'=> $user));
|
||
}
|
||
|
||
/**
|
||
* Manage scope.
|
||
* 维护范围。
|
||
*
|
||
* @access public
|
||
* @return void
|
||
*/
|
||
public function manageScope()
|
||
{
|
||
$scopeList = $this->doc->getTemplateScopes();
|
||
|
||
if(!empty($_POST))
|
||
{
|
||
$scopes = $this->post->scopes;
|
||
|
||
$oldScopes = $newScopes = array();
|
||
foreach($scopes as $index => $name)
|
||
{
|
||
if(empty(trim($name))) continue;
|
||
|
||
$scopeID = $_POST['id'][$index];
|
||
if($scopeID)
|
||
{
|
||
$oldScopes[$scopeID] = $name;
|
||
}
|
||
else
|
||
{
|
||
$newScopes[$index] = $name;
|
||
}
|
||
}
|
||
|
||
$deletedScopes = array_diff(array_keys($scopeList), array_keys($oldScopes));
|
||
if(!empty($deletedScopes)) $this->doc->deleteTemplateScopes($deletedScopes);
|
||
if(dao::isError()) return $this->sendError(array('message' => dao::getError()));
|
||
|
||
if(!empty($oldScopes)) $this->doc->updateTemplateScopes($oldScopes);
|
||
if(dao::isError()) return $this->sendError(array('message' => dao::getError()));
|
||
|
||
if(!empty($newScopes)) $this->doc->insertTemplateScopes($newScopes);
|
||
if(dao::isError()) return $this->sendError(array('message' => dao::getError()));
|
||
|
||
return $this->sendSuccess(array('closeModal' => true, 'load' => true));
|
||
}
|
||
|
||
$this->view->scopeList = $scopeList;
|
||
$this->display();
|
||
}
|
||
|
||
/**
|
||
* AJAX: Judge can be deleted scope.
|
||
* AJAX: 判断范围是否可以被删除。
|
||
*
|
||
* @param int $scopeID
|
||
* @access public
|
||
* @return array
|
||
*/
|
||
public function ajaxJudgeCanBeDeleted(int $scopeID = 0)
|
||
{
|
||
if(empty($scopeID)) return $this->sendSuccess(array('message' => 'success'));
|
||
|
||
$templates = $this->doc->getScopeTemplates(array($scopeID));
|
||
if(!empty($templates[$scopeID])) return $this->sendError($this->lang->docTemplate->scopeHasTemplateTips);
|
||
|
||
$modules = $this->doc->getTemplateModules($scopeID);
|
||
if(!empty($modules)) return $this->sendError($this->lang->docTemplate->scopeHasModuleTips);
|
||
|
||
return $this->sendSuccess(array('message' => 'success'));
|
||
}
|
||
}
|