znt/module/action/tao.php

1060 lines
42 KiB
PHP

<?php
declare(strict_types=1);
class actionTao extends actionModel
{
/**
* 获取一个action的基础数据。
* Fetch base info of a action.
*
* @param int $actionID
* @access public
* @return object|bool
*/
public function fetchBaseInfo(int $actionID): object|bool
{
return $this->dao->select('*')->from(TABLE_ACTION)->where('id')->eq($actionID)->fetch();
}
/**
* 获取一个基础对象的信息。
* Get object base info.
*
* @param string $table
* @param array $queryParam
* @param string $field
* @param string $orderby
* @access public
* @return object|bool
*/
public function getObjectBaseInfo(string $table, array $queryParam, string $field = '*', string $orderby = ''): object|bool
{
$querys = array_map(function($key, $query){return "`{$key}` = '{$query}'";}, array_keys($queryParam), $queryParam);
return $this->dao->select($field)->from($table)->where(implode(' and ', $querys))->orderby($orderby)->fetch();
}
/**
* 获取无需过滤的关联关系。
* Get no filter required relation.
*
* @param string $objectType
* @param int $objectID
* @access public
* @return array
*/
public function getNoFilterRequiredRelation(string $objectType, int $objectID): array
{
$product = array(0);
$project = $execution = 0;
switch($objectType)
{
case 'product':
$product = array($objectID);
break;
case 'project':
case 'execution':
$products = $this->dao->select('product')->from(TABLE_PROJECTPRODUCT)->where('project')->eq($objectID)->fetchPairs();
if($products) $product = $products;
${$objectType} = $objectID;
if($objectType == 'execution')
{
$project = $this->dao->select('project')->from(TABLE_EXECUTION)->where('id')->eq($objectID)->fetch('project');
if(!$project) $project = 0;
}
break;
case 'marketresearch':
$project = $objectID;
break;
}
return array($product, $project, $execution);
}
/**
* 获取对象的产品项目以及执行。
* Get product, project, execution of the object.
*
* @param string $objectType
* @param int $objectID
* @param string $actionType
* @param string $extra
* @access public
* @return array
*/
public function getNeedRelatedFields(string $objectType, int $objectID, string $actionType = '', string $extra = ''): array
{
$product = array(0);
$project = $execution = 0;
switch($objectType)
{
case 'story':
list($product, $project, $execution) = $this->getStoryActionRelated($objectType, $actionType, $objectID, (int)$extra);
break;
case 'productplan':
case 'branch':
$product = $objectID == 0 ? $extra : $this->dao->select('product')->from($this->config->objectTables[$objectType])->where('id')->eq($objectID)->fetch('product');
break;
case 'testcase':
case 'case':
list($product, $project, $execution) = $this->getCaseRelated($objectType, $actionType, $objectID, (int)$extra);
break;
case 'repo':
case 'nc':
case 'kanbanlane':
$execution = $this->dao->select('execution')->from($this->config->objectTables[$objectType])->where('id')->eq($objectID)->fetch('execution');
break;
case 'release':
list($product, $project) = $this->getReleaseRelated($objectType, $objectID);
break;
case 'task':
list($product, $project, $execution) = $this->getTaskRelated($objectType, $objectID);
break;
case 'kanbancolumn':
$execution = $extra;
break;
case 'team':
$type = $this->dao->select('type')->from(TABLE_PROJECT)->where('id')->eq($objectID)->fetch('type');
if($type != 'project') $type = 'execution';
${$type} = $objectID;
break;
case 'whitelist':
if($extra == 'product' || $extra == 'project') ${$extra} = $objectID;
if($extra == 'sprint' || $extra == 'stage') $execution = $objectID;
break;
case 'module':
$moduleID = $actionType != 'deleted' ? (int)$extra : (int)$objectID;
$module = $this->dao->select('type,root')->from(TABLE_MODULE)->where('id')->eq($moduleID)->fetch();
if(!empty($module) && $module->type == 'story') $product = array($module->root);
break;
case 'review':
case 'cm':
case 'projectchange':
list($product, $project) = $this->getReviewRelated($objectType, $objectID);
break;
default:
list($product, $project, $execution) = $this->getGenerateRelated($objectType, $objectID);
break;
}
return array($product, $project, $execution);
}
/**
* 获取用户故事相关的产品、项目、阶段。
* Get story related product, project, stage.
*
* @param string $objectType
* @param string $actionType
* @param int $objectID
* @param int $extra
* @access public
* @return array
*/
public function getStoryActionRelated(string $objectType, string $actionType, int $objectID, int $extra): array
{
list($product, $project, $execution) = $this->getGenerateRelated($objectType, $objectID);
switch($actionType)
{
case 'linked2build':
case 'unlinkedfrombuild':
$build = $this->dao->select('project,execution')->from(TABLE_BUILD)->where('id')->eq($extra)->fetch();
if($build)
{
$project = $build->project;
$execution = $build->execution;
}
break;
case 'estimated':
$project = $this->dao->select('project')->from(TABLE_EXECUTION)->where('id')->eq($extra)->fetch('project');
$execution = (int)$extra;
break;
default:
$projectList = $this->dao->select('t2.id,t2.project,t2.type')->from(TABLE_PROJECTSTORY)->alias('t1')
->leftJoin(TABLE_PROJECT)->alias('t2')->on('t1.project = t2.id')
->where('t1.story')->eq($objectID)
->fetchAll();
foreach($projectList as $projectInfo)
{
if($projectInfo->type == 'project')
{
$project = $projectInfo->id;
continue;
}
$project = $projectInfo->project;
$execution = $projectInfo->id;
}
break;
}
return array($product, $project, $execution);
}
/**
* 获取用例相关的产品、项目、阶段。
* Get case related product, project, stage.
*
* @param string $objectType
* @param string $actionType
* @param string $table
* @param int $objectID
* @param int $extra
* @access public
* @return array
*/
public function getCaseRelated(string $objectType, string $actionType, int $objectID, int $extra): array
{
list($product, $project, $execution) = $this->getGenerateRelated($objectType, $objectID);
if(in_array($actionType, array('linked2testtask', 'unlinkedfromtesttask', 'run')) && $extra)
{
$testtask = $this->dao->select('project,execution')->from(TABLE_TESTTASK)->where('id')->eq($extra)->fetch();
$project = $testtask->project;
$execution = $testtask->execution;
}
return array($product, $project, $execution);
}
/**
* 常规获取相关的产品、项目、执行。
* Get general related product, project, execution.
*
* @param string $objectType
* @param int $objectID
* @access public
* @return array
*/
public function getGenerateRelated(string $objectType, int $objectID): array
{
$product = $project = $execution = 0;
if(!isset($this->config->objectTables[$objectType])) return array(array($product), $project, $execution);
$result = $this->dao->select('*')->from($this->config->objectTables[$objectType])->where('id')->eq($objectID)->fetch();
if($result)
{
$product = zget($result, 'product', 0);
$project = zget($result, 'project', 0);
$execution = zget($result, 'execution', 0);
}
return array(array($product), $project, $execution);
}
/**
* 获取分支相关的产品、项目、执行。
* Get case related product, project, execution.
*
* @param string $objectType
* @param int $objectID
* @access public
* @return array
*/
public function getReleaseRelated(string $objectType, int $objectID): array
{
$product = 0;
$project = 0;
$result = $this->dao->select('product, build')->from($this->config->objectTables[$objectType])->where('id')->eq($objectID)->fetch();
if($result)
{
$product = $result->product;
$project = $this->dao->select('project')->from(TABLE_BUILD)->where('id')->in($result->build)->fetch('project');
}
return array(array($product), $project);
}
/**
* 获取任务相关的产品、项目、执行。
* Get task related product, project, execution.
*
* @param string $objectType
* @param int $objectID
* @access public
* @return array
*/
public function getTaskRelated(string $objectType, int $objectID): array
{
$product = array(0);
$project = $execution = 0;
$result = $this->dao->select('project,execution,story')->from($this->config->objectTables[$objectType])->where('id')->eq($objectID)->fetch();
if($result)
{
$table = $result->story != 0 ? TABLE_STORY : TABLE_PROJECTPRODUCT;
$field = $result->story != 0 ? 'id' : 'project';
$value = $result->story != 0 ? $result->story : $result->execution;
$products = $this->dao->select('product')->from($table)->where($field)->eq($value)->fetchPairs();
if($products) $product = array_values($products);
$project = $result->project;
$execution = $result->execution;
}
return array($product, $project, $execution);
}
/**
* 获取需求相关的产品、项目、执行。
* Get story related product, project, execution.
*
* @param string $objectType
* @param int $objectID
* @access public
* @return array
*/
public function getReviewRelated(string $objectType, int $objectID): array
{
$product = array(0);
$project = 0;
$result = $this->dao->select('*')->from($this->config->objectTables[$objectType])->where('id')->eq($objectID)->fetch();
if($result)
{
$products = $this->dao->select('product')->from(TABLE_PROJECTPRODUCT)->where('project')->eq($result->project)->fetchPairs();
if($products) $product = $products;
$project = zget($result, 'project', 0);
}
return array($product, $project);
}
/**
* 根据类型和ID获取操作记录列表。
* Get action list by type and ID.
*
* @param string $objectType
* @param int $objectID
* @param array $modules
* @access public
* @return array
*/
public function getActionListByTypeAndID(string $objectType, array|int $objectID, array $modules): array
{
$subTables = array();
if($this->config->edition != 'open')
{
$subTables = $this->dao->select('module')->from(TABLE_WORKFLOW)
->where('parent')->eq($objectType)
->andWhere('type')->eq('table')
->fetchPairs();
}
return $this->dao->select('*')->from(TABLE_ACTION)
->beginIF($objectType == 'project')
->where("objectType IN('project', 'testtask', 'build')")
->andWhere('project')->in($objectID)
->fi()
->beginIF($objectType == 'story')
->where('objectType')->in('story,requirement')
->andWhere('objectID')->in($objectID)
->fi()
->beginIF($objectType == 'case' || $objectType == 'testcase')
->where('objectType')->in('case,testcase')
->andWhere('objectID')->in($objectID)
->fi()
->beginIF($objectType == 'module')
->where('objectType')->eq($objectType)
->andWhere('((action')->ne('deleted')->andWhere('objectID')->in($objectID)->markRight(1)
->orWhere('(action')->eq('deleted')->andWhere('objectID')->in($modules)->markRight(1)->markRight(1)
->fi()
->beginIF(!empty($subTables))
->where('(objectType')->eq($objectType)
->andWhere('objectID')->in($objectID)
->markRight(1)
->orWhere('(objectType')->in($subTables)
->andWhere('extra')->in($objectID)
->markRight(1)
->fi()
->beginIF(empty($subTables) && !in_array($objectType, array('project', 'case', 'testcase', 'story', 'module')))
->where('objectType')->eq($objectType)
->andWhere('objectID')->in($objectID)
->fi()
->orderBy('date, id')
->fetchAll('id', false);
}
/**
* 获取 linked 和 unlinked 操作记录的附加信息。
* Get action extra info.
*
* @param object $action
* @param string $type
* @access public
* @return bool
*/
public function getLinkedExtra(object $action, string $type): bool
{
if($type == 'plan') $type = 'productplan';
if($type == 'revision') $type = 'repohistory';
if($type == 'bug') $type = 'build';
if($type == 'roadmap' && $action->objectType == 'story') $type = 'roadmap';
$table = zget($this->config->objectTables, $type, '');
if(empty($table)) return false;
$method = 'view';
if(in_array($type, array('execution', 'kanban')))
{
$execution = $this->fetchObjectInfoByID(TABLE_EXECUTION, (int)$action->extra, 'name, type, multiple');
if(!$execution) return false;
if($execution->type != 'project' && empty($execution->multiple)) return false;
$name = $execution->name;
if($execution->type == 'kanban') $method = 'kanban';
if($name)
{
$isModalKanban = $method == 'kanban' && isonlybody();
$canShowLink = common::hasPriv('execution', $method) && !$isModalKanban && $this->config->vision != 'or';
$action->extra = $canShowLink ? html::a(helper::createLink('execution', $method, "executionID={$action->execution}"), $name, '', "data-app='execution'") : $name;
}
}
elseif($type == 'project')
{
$project = $this->fetchObjectInfoByID($table, (int)$action->extra, 'name, model, multiple');
if(!$project) return false;
$name = $project->name;
if($project->model == 'kanban') $method = $project->multiple ? 'kanban' : 'index';
if($name) $action->extra = (common::hasPriv('project', $method) and $this->config->vision != 'or') ? html::a(helper::createLink('project', $method, "projectID=$action->project"), $name, '_self', in_array($method, array('view', 'index')) ? 'data-app="project"' : '') : $name;
}
elseif($type == 'plan' || $type == 'productplan')
{
$plan = $this->fetchObjectInfoByID($table, (int)$action->extra, 'title');
if($plan && $plan->title) $action->extra = common::hasPriv('productplan', 'view') && $this->config->vision != 'or' ? html::a(helper::createLink('productplan', $method, "planID={$action->extra}"), $plan->title) : $plan->title;
}
elseif(in_array($type, array('build', 'bug', 'release', 'testtask', 'roadmap')))
{
$field = $type == 'build' ? 'name, execution' : 'name';
$object = $this->fetchObjectInfoByID($table, (int)$action->extra, $field);
$buildTab = $type == 'build' && (in_array($this->app->tab, array('product', 'qa')) || empty($action->execution)) ? 'project' : $this->app->tab;
if($this->app->tab == 'system') $buildTab = 'project';
if($object && $object->name) $action->extra = common::hasPriv($type, $method) ? html::a(helper::createLink($type, $method, $this->processParamString($action, $type)), $object->name, '', $type == 'build' ? "data-app='{$buildTab}'" : '') : $object->name;
}
elseif($type == 'revision')
{
$commit = $this->fetchObjectInfoByID($table, $action->extra, 'repo, revision');
if($commit)
{
$revision = substr($commit->revision, 0, 10);
$action->extra = common::hasPriv('repo', 'revision') ? html::a(helper::createLink('repo', 'revision', "repoID={$commit->repo}&objectID=0&revision={$commit->revision}"), $revision) : $revision;
}
}
return true;
}
/**
* 通过ID获取对象信息。
* Get object info by ID.
*
* @param string $table
* @param int $objectID
* @access public
* @return object|bool
*/
public function fetchObjectInfoByID(string $table, int $objectID, string $field = '*'): object|bool
{
return $this->dao->select($field)->from($table)->where('id')->eq($objectID)->fetch();
}
/**
* 组建Action的extra信息。
* Build action extra info.
*
* @param string $table
* @param object $action
* @param string $fields
* @param string $type
* @param string $method
* @param bool $onlyBody
* @param bool $addlink
* @access public
* @return void
*/
public function processActionExtra(string $table, object $action, string $fields, string $type, string $method = 'view', bool $onlyBody = false, bool $addLink = true): void
{
$object = $this->fetchObjectInfoByID($table, (int)$action->extra, $fields);
$condition = common::hasPriv($type, $method);
if($onlyBody) $condition = $condition && !isonlybody();
if($object && $object->{$fields})
{
$misc = '';
if($action->objectType == 'bug' && $action->action == 'converttotask' && $type == 'task' && $method == 'view')
{
$misc = "data-app='execution'";
$isMultipleProject = $this->dao->select('multiple')->from(TABLE_PROJECT)->where('id')->eq($action->project)->fetch('multiple');
if(!$isMultipleProject) $misc = "data-app='project'";
}
$action->extra = $condition && $addLink ? html::a(helper::createLink($type, $method, $this->processParamString($action, $type)), "#{$action->extra} " . $object->{$fields}, '', $misc) : "#{$action->extra} " . $object->{$fields};
}
}
/**
* 处理需求层级。
* Process story grade.
*
* @param object $action
* @access public
* @return object
*/
public function processStoryGradeActionExtra($action): object
{
$action->extra = $this->dao->select('t1.name')->from(TABLE_STORYGRADE)->alias('t1')
->leftJoin(TABLE_STORY)->alias('t2')->on('t1.grade = t2.grade AND t1.type = t2.type')
->where('t2.id')->eq($action->objectID)
->fetch('name');
return $action;
}
/**
* 处理属性。
* Process attribute.
*
* @param string $type
* @access public
* @return string
*/
public function processAttribute($type): string
{
if($type == 'testtask') $type = 'task';
return $type;
}
/**
* 处理参数字符串。
* Process param string.
*
* @param object $action
* @param string $type
* @access public
* @return string
*/
public function processParamString(object $action, string $type): string
{
$paramString = '';
switch($type)
{
case 'build':
case 'bug':
case 'release':
$attribute = $this->processAttribute($type);
$paramString = "{$attribute}ID={$action->extra}&type={$action->objectType}";
break;
case 'testtask':
$paramString = "taskID={$action->extra}";
break;
case 'execution':
case 'kanban':
case 'story':
$paramString = "{$type}ID={$action->extra}";
break;
case 'task':
case 'story':
case 'charter':
$paramString = "{$type}ID={$action->extra}";
break;
case 'project':
$productID = trim($action->product, ',');
$paramString = "{$type}ID={$action->execution}&productID={$productID}";
break;
case 'productplan':
$paramString = "planID={$action->extra}";
break;
case 'caselib':
$paramString = "libID={$action->extra}";
break;
case 'roadmap':
$paramString = "roadmapID={$action->extra}";
break;
case 'assetlib':
$paramString = "libID={$action->extra}";
break;
case 'demand':
$paramString = "demandID={$action->extra}";
break;
case 'epic':
$paramString = "storyID={$action->extra}";
break;
}
return $paramString;
}
/**
* 搭建创建子任务的Action的extra信息。
* Build create children action extra info.
*
* @param object $action
* @access public
* @return void
*/
public function processCreateChildrenActionExtra(object $action): void
{
$names = $this->dao->select('id,name')->from(TABLE_TASK)->where('id')->in($action->extra)->fetchPairs();
$action->extra = '';
if($names)
{
foreach($names as $id => $name) $action->extra .= common::hasPriv('task', 'view') ? html::a(helper::createLink('task', 'view', "taskID={$id}"), "#{$id} " . $name) . ', ' : "#{$id} " . $name . ', ';
}
$action->extra = trim(trim($action->extra), ',');
}
/**
* 搭建创建需求的Action的extra信息。
* Build create requirement action extra info.
*
* @param object $action
* @access public
* @return void
*/
public function processCreateRequirementsActionExtra(object $action): void
{
$names = $this->dao->select('id,title')->from(TABLE_STORY)->where('id')->in($action->extra)->fetchPairs();
$action->extra = '';
if($names)
{
foreach($names as $id => $name) $action->extra .= common::hasPriv('requriement', 'view') ? html::a(helper::createLink('story', 'view', "storyID={$id}"), "#{$id} " . $name) . ', ' : "#{$id} " . $name . ', ';
}
$action->extra = trim(trim($action->extra), ',');
}
/**
* 通过 extra 获取对象的 appendLink。
* Get object appendLink by extra.
*
* @param object $action
* @access public
* @return void
*/
public function processAppendLinkByExtra(object $action): void
{
$action->appendLink = '';
if(strpos($action->extra, '|') !== false) $action->extra = substr($action->extra, 0, strpos($action->extra, '|'));
if(strpos($action->extra, ':') !== false)
{
list($extra, $id) = explode(':', $action->extra);
if($id)
{
$extra = strtolower($extra);
$module = $action->objectType == 'todo' ? $extra : $action->objectType;
$table = $this->config->objectTables[$module];
$field = $this->config->action->objectNameFields[$module];
$name = $this->dao->select($field)->from($table)->where('id')->eq($id)->fetch($field);
$method = $module == 'story' ? 'storyView' : 'view';
if($name) $action->appendLink = html::a(helper::createLink($module, $method, "id={$id}"), "#{$id} " . $name);
}
$action->extra = $extra;
}
}
/**
* 搭建关联用户故事和bug的Action的extra信息。
* Build link story and bug action extra info.
*
* @param object $action
* @param string $module
* @param string $method
* @access public
* @return void
*/
public function processLinkStoryAndBugActionExtra(object $action, string $module, string $method): void
{
$extra = '';
foreach(explode(',', $action->extra) as $id) $extra .= common::hasPriv($module, $method) ? html::a(helper::createLink($module, $method, "{$module}ID={$id}"), "#{$id} ", '', "data-size='lg' data-toggle='modal'") . ', ' : "#{$id}, ";
$action->extra = trim(trim($extra), ',');
}
/**
* 搭建与用户故事相关的Action的extra信息。
* Build story related action extra info.
*
* @param object $action
* @access public
* @return void
*/
public function processToStoryActionExtra(object $action): void
{
$productShadow = $this->dao->select('shadow')->from(TABLE_PRODUCT)->where('id')->in(trim($action->product, ','))->fetch('shadow');
$title = $this->dao->select('title')->from(TABLE_STORY)->where('id')->eq($action->extra)->fetch('title');
$defaultExtra = "#{$action->extra} {$title}";
if($productShadow)
{
$projectID = $this->dao->select('project')->from(TABLE_PROJECTSTORY)->where('story')->eq($action->extra)->fetch('project');
if($title) $action->extra = common::hasPriv('projectstory', 'view') && $projectID ? html::a(helper::createLink('projectstory', 'view', "storyID={$action->extra}&projectID={$projectID}"), $defaultExtra) : $defaultExtra;
}
else
{
if($title) $action->extra = common::hasPriv('story', 'view') ? html::a(helper::createLink('story', 'view', "storyID={$action->extra}"), $defaultExtra) : $defaultExtra;
}
}
/**
* 通过条件获取操作记录列表。
* Get action list by condition.
*
* @param string $condition
* @param string $begin
* @param string $end
* @param string $account
* @param string|int $productID
* @param string|int $projectID
* @param string|int $executionID
* @param string $actionCondition
* @param string $orderBy
* @param int $limit
* @access public
* @return array|bool
*/
public function getActionListByCondition(string $condition, string $begin, string $end, string $account, string|int $productID, string|int $projectID, string|int $executionID, string $actionCondition, string $orderBy, int $limit = 50): array|bool
{
/* 获取最近一个月的动态用actionrecent表。 */
$lastMonth = date('Y-m-d', strtotime('-1 month'));
$actionTable = ($begin >= $lastMonth && $end >= $lastMonth) ? TABLE_ACTIONRECENT : TABLE_ACTION;
$actionCondition = str_replace(' `action`', ' action.`action`', $actionCondition);
$hasProduct = preg_match('/t2\.(`?)product/', $condition);
if(is_numeric($productID) && $productID) $hasProduct = true;
if($productID === 'notzero') $hasProduct = true;
return $this->dao->select('action.*')->from($actionTable)->alias('action')
->beginIF($hasProduct)->leftJoin(TABLE_ACTIONPRODUCT)->alias('t2')->on('action.id=t2.action')->fi()
->where('objectType')->notIN($this->config->action->ignoreObjectType4Dynamic)
->andWhere('action.action')->notIN($this->config->action->ignoreActions4Dynamic)
->andWhere('vision')->eq($this->config->vision)
->beginIF($begin != EPOCH_DATE)->andWhere('date')->ge($begin)->fi()
->beginIF($end != FUTURE_DATE)->andWhere('date')->le($end)->fi()
->beginIF($account != 'all')->andWhere('actor')->eq($account)->fi()
->beginIF(is_numeric($productID) && $productID)->andWhere('t2.product')->eq($productID)->fi()
->beginIF(is_numeric($projectID) && $projectID)->andWhere('project')->eq($projectID)->fi()
->beginIF(is_numeric($executionID) && $executionID)->andWhere('execution')->eq($executionID)->fi()
/* lite模式下需要排除的一些类型。 */
/* Types excluded from Lite. */
->beginIF($this->config->vision == 'lite')->andWhere('objectType')->notin('product')->fi()
->beginIF($this->config->systemMode == 'light')->andWhere('objectType')->notin('program')->fi()
->beginIF($productID === 'notzero')->andWhere('t2.product')->gt(0)->fi()
->beginIF($projectID === 'notzero')->andWhere('project')->gt(0)->fi()
->beginIF($executionID === 'notzero')->andWhere('execution')->gt(0)->fi()
->beginIF($condition && $condition != '1=1')->andWhere($condition)->fi()
->beginIF($actionCondition)->andWhere("($actionCondition)")->fi()
->orderBy($orderBy)
->limit($limit)
->fetchAll('', false);
}
/**
* 根据条件获取动态表。
* Get action table by condition.
*
* @param string $period
* @access public
* @return string
*/
public function getActionTable(string $period): string
{
return in_array($period, $this->config->action->latestDateList) ? TABLE_ACTIONRECENT : TABLE_ACTION;
}
/**
* 检查Action是否合法。
* Check if action is legal.
*
* @param object $action
* @param array $shadowProducts
* @param array $docList
* @param array $apiList
* @param array $docLibList
* @access public
* @return bool
*/
public function checkIsActionLegal(object $action, array $shadowProducts, array $docList, array $apiList, array $docLibList): bool
{
if(($action->objectType == 'doc' || $action->objectType == 'doctemplate') && !isset($docList[$action->objectID])) return false;
if($action->objectType == 'api' && !isset($apiList[$action->objectID])) return false;
if($action->objectType == 'doclib' && !isset($docLibList[$action->objectID])) return false;
if($action->objectType == 'product' && isset($shadowProducts[$action->objectID])) return false;
return true;
}
/**
* 为Action添加对象名称。
* Add object name for action.
*
* @param object $action
* @param array $objectNames
* @param string $objectType
* @access public
* @return void
*/
public function addObjectNameForAction(object $action, array $objectNames, string $objectType)
{
$action->objectName = isset($objectNames[$action->objectType][$action->objectID]) ? $objectNames[$action->objectType][$action->objectID] : '';
if($action->objectType == 'program' && strpos('syncexecution,syncproject,syncprogram', $action->action) !== false)
{
$action->objectName .= $this->lang->action->label->startProgram;
}
elseif($action->objectType == 'branch' && $action->action == 'mergedbranch')
{
if($action->objectID == 0) $action->objectName = $this->lang->branch->main;
$action->objectName = '"' . $action->extra . ' "' . $this->lang->action->to . ' "' . $action->objectName . '"';
}
elseif($action->objectType == 'user')
{
$user = $this->dao->select('id,realname')->from(TABLE_USER)->where('id')->eq($action->objectID)->fetch();
if($user) $action->objectName = $user->realname;
}
elseif($action->objectType == 'kanbancard' && strpos($action->action, 'imported') !== false && $action->action != 'importedcard')
{
$objectType = str_replace('imported', '', $action->action);
$objectTable = zget($this->config->objectTables, $objectType, '');
$objectName = ($objectType == 'productplan' || $objectType == 'ticket') ? 'title' : 'name';
if($objectTable) $action->objectName = $this->dao->select($objectName)->from($objectTable)->where('id')->eq($action->extra)->fetch($objectName);
}
elseif(strpos(',module,chartgroup,', ",$action->objectType,") !== false && !empty($action->extra) && $action->action != 'deleted')
{
$modules = $this->dao->select('id,name')->from(TABLE_MODULE)->where('id')->in(explode(',', $action->extra))->fetchPairs('id');
$action->objectName = implode(',', $modules);
}
elseif($action->objectType == 'mr' && $action->action == 'deleted')
{
$action->objectName = $action->extra;
}
elseif($action->objectType == 'pivot')
{
$pivotNames = json_decode($action->objectName, true);
$action->objectName = zget($pivotNames, $this->app->getClientLang(), '');
if(empty($action->objectName))
{
$pivotNames = array_filter($pivotNames);
$action->objectName = reset($pivotNames);
}
}
elseif($action->objectType == 'aiassistant')
{
$action->objectName = $this->dao->select('name')->from(TABLE_AI_ASSISTANT)->where('id')->eq($action->objectID)->fetch('name');
}
if (empty($action->objectName) && preg_match('/^(gitlab|gitea|gogs|mr)/', $objectType)) $action->objectName = $action->extra;
}
/**
* 旗舰版处理资产库的链接。
* Process doc link for max.
*
* @param object $action
* @param string $moduleName
* @param string $methodName
* @param string $vars
* @access public
* @return void
*/
public function processMaxDocObjectLink(object $action, string $moduleName, string $methodName, string $vars)
{
if($action->objectType == 'doc')
{
$assetLibType = $this->dao->select('assetLibType')->from(TABLE_DOC)->where('id')->eq($action->objectID)->fetch('assetLibType');
if($assetLibType) $method = $assetLibType == 'practice' ? 'practiceView' : 'componentView';
}
else
{
$method = $this->config->action->assetViewMethod[$action->objectType];
}
if(isset($method))
{
$moduleName = 'assetlib';
$methodName = $method;
}
$action->objectLink = common::hasPriv($moduleName, $methodName) ? helper::createLink($moduleName, $methodName, sprintf($vars, $action->objectID)) : '';
$action->hasLink = true;
}
/**
* 获取文档库链接参数。
* Get doclib link params.
*
* @param object $action
* @access public
* @return array|bool
*/
public function getDocLibLinkParameters(object $action)
{
$libID = $action->objectID;
$type = 'custom';
if(!empty($action->project)) $type = 'project';
if(!empty($action->execution)) $type = 'execution';
if(!empty($action->product)) $type = 'product';
$libObjectID = $type != 'custom' ? $action->{$type} : '';
$libObjectID = trim($libObjectID, ',');
if(empty($libObjectID) && $type != 'custom') return false;
return array($type, $libID, $libObjectID);
}
/**
* 获取文档库类型参数。
* Get doclib type params.
*
* @param object $action
* @access public
* @return array
*/
public function getDoclibTypeParams(object $action): array
{
$params = '';
$docLib = $this->dao->select('type,product,project,execution,deleted')->from(TABLE_DOCLIB)->where('id')->eq($action->objectID)->fetch();
$docLib->objectID = in_array($docLib->type, array('product', 'project', 'execution')) ? $docLib->{$docLib->type} : 0;
$appendLib = $docLib->deleted == '1' ? $action->objectID : 0;
if($docLib->type == 'api')
{
$moduleName = 'api';
$methodName = 'index';
$params = "libID={$action->objectID}&moduleID=0&apiID=0&version=0&release=0&appendLib={$appendLib}";
if(!empty($docLib->project) || !empty($docLib->product))
{
$moduleName = 'doc';
if(!empty($docLib->product))
{
$objectID = $docLib->product;
$methodName = 'productspace';
}
if(!empty($docLib->project))
{
$objectID = $docLib->project;
$methodName = 'projectspace';
}
$params = "objectID={$objectID}&libID={$action->objectID}";
}
}
else
{
$moduleName = 'doc';
$methodName = zget($this->config->doc->spaceMethod, $docLib->type, 'tablecontents');
if($methodName == 'myspace') $params = "type=mine&libID={$action->objectID}";
if(!in_array($methodName, array('myspace', 'tablecontents'))) $params = "objectID={$docLib->objectID}&libID={$action->objectID}";
}
return array($moduleName, $methodName, $params);
}
/**
* 检查Action是否可点击。
* Check if action is clickable.
*
* @param object $action
* @param array $deptUsers
* @param string $moduleName
* @param string $methodName
* @access public
* @return bool
*/
public function checkActionClickable(object $action, array $deptUsers, string $moduleName, string $methodName): bool
{
if(empty($moduleName) || empty($methodName)) return false;
if(!common::hasPriv($moduleName, $methodName)) return false;
if(!helper::hasFeature($moduleName)) return false;
if($action->objectType == 'user' && !isset($deptUsers[$action->objectID]) && !$this->app->user->admin) return false;
if($action->objectType == 'user' && ($action->action == 'login' || $action->action == 'logout')) return false;
if($action->objectType == 'user')
{
$user = $this->dao->select('deleted')->from(TABLE_USER)->where('id')->eq($action->objectID)->fetch();
if($user && $user->deleted == '1') return false;
}
if($action->objectType == 'todo')
{
$todo = $this->dao->select('*')->from(TABLE_TODO)->where('id')->eq($action->objectID)->fetch();
if($todo && $todo->private == 1 && $todo->account != $this->app->user->account) return false;
}
if($action->objectType == 'docTemplate' && !common::hasPriv('docTempalte', 'view')) return false;
if($action->objectType == 'mr' && (empty($action->objectName) || $action->action == 'deleted')) return false;
if($action->objectType == 'stakeholder' && $action->project == 0) return false;
if($action->objectType == 'chartgroup') return false;
if($action->objectType == 'branch' && $action->action == 'mergedbranch') return false;
if($action->objectType == 'case')
{
$case = $this->dao->select('lib')->from(TABLE_CASE)->where('id')->eq($action->objectID)->fetch();
if($action->action == 'tolib' || !empty($case->lib)) return helper::hasFeature('caselib');
}
return true;
}
/**
* 获取对象链接参数。
* Get object link params.
*
* @param object $action
* @param string $vars
* @access public
* @return string
*/
public function getObjectLinkParams(object $action, string $vars): string
{
if($action->objectType == 'api')
{
$api = $this->dao->select('id,lib,module')->from(TABLE_API)->where('id')->eq($action->objectID)->fetch();
$params = sprintf($vars, $api->lib, $api->id, $api->module);
}
elseif($action->objectType == 'branch' || ($action->objectType == 'module' && $action->action == 'deleted'))
{
$params = sprintf($vars, trim($action->product, ','));
}
elseif($action->objectType == 'kanbanspace')
{
$kanbanSpace = $this->dao->select('type')->from(TABLE_KANBANSPACE)->where('id')->eq($action->objectID)->fetch();
$params = sprintf($vars, $kanbanSpace->type);
}
elseif($action->objectType == 'kanbancard')
{
$table = $this->config->objectTables[$action->objectType];
$kanbanID = $this->dao->select('kanban')->from($table)->where('id')->eq($action->objectID)->fetch('kanban');
$params = sprintf($vars, $kanbanID);
}
elseif($action->objectType == 'module' && $action->action == 'undeleted')
{
$table = $this->config->objectTables[$action->objectType];
$moduleID = $this->dao->select('root')->from($table)->where('id')->eq($action->objectID)->fetch('root');
$params = sprintf($vars, $moduleID);
}
else
{
$params = sprintf($vars, $action->objectID);
}
return $params;
}
/**
* 根据对象类型获取恢复对象参数。
* Get object params by object type.
*
* @param string $objectType
* @access public
* @return array
*/
public function getUndeleteParamsByObjectType(string $objectType): array
{
$table = $this->config->objectTables[$objectType];
$orderby = '';
$field = '*';
$queryKey = 'id';
switch($objectType)
{
case 'product':
$field = 'id, name, code, acl';
break;
case 'program':
case 'project':
$field = 'id, acl, name, hasProduct, multiple';
break;
case 'doc':
$table = TABLE_DOCCONTENT;
$orderby = 'version desc';
$queryKey = 'doc';
default:
break;
}
return array($table, $orderby, $field, $queryKey);
}
}