znt/module/group/model.php

1121 lines
39 KiB
PHP
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<?php
declare(strict_types=1);
/**
* The model file of group 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 group
* @version $Id: model.php 4976 2013-07-02 08:15:31Z wyd621@gmail.com $
* @link https://www.zentao.net
*/
class groupModel extends model
{
/**
* 创建一个分组。
* Create a group.
*
* @access public
* @return bool
*/
public function create(object $group): int|false
{
if(isset($group->limited))
{
unset($group->limited);
$group->role = 'limited';
}
if(!isset($group->vision)) $group->vision = $this->config->vision;
$this->lang->error->unique = $this->lang->group->repeat;
$this->dao->insert(TABLE_GROUP)->data($group)
->check('name', 'unique', "vision = '{$this->config->vision}' and project='{$group->project}'")
->exec();
if(dao::isError()) return false;
$groupID = $this->dao->lastInsertId();
$data = new stdclass();
$data->group = $groupID;
$data->module = 'index';
$data->method = 'index';
$this->dao->replace(TABLE_GROUPPRIV)->data($data)->exec();
return $groupID;
}
/**
* 更新权限分组。
* Update a group.
*
* @param int $groupID
* @param object $group
* @access public
* @return void
*/
public function update(int $groupID, object $group): bool
{
$this->lang->error->unique = $this->lang->group->repeat;
$this->dao->update(TABLE_GROUP)->data($group)
->where('id')->eq($groupID)
->exec();
return !dao::isError();
}
/**
* 复制一个分组。
* Copy a group.
*
* @param int $groupID
* @param object $group
* @param array $options
* @access public
* @return int|false
*/
public function copy(int $groupID, object $group, array $options): int|false
{
$this->lang->error->unique = $this->lang->group->repeat;
$this->dao->insert(TABLE_GROUP)->data($group)
->check('name', 'unique', "vision = '{$this->config->vision}' and project = '{$group->project}'")
->exec();
if(dao::isError()) return false;
$newGroupID = $this->dao->lastInsertID();
if(empty($options)) return $newGroupID;
if(in_array('copyPriv', $options)) $this->copyPriv($groupID, $newGroupID);
if(in_array('copyUser', $options)) $this->copyUser($groupID, $newGroupID);
return $newGroupID;
}
/**
* 复制分组的权限。
* Copy privileges.
*
* @param int $fromGroup
* @param int $toGroup
* @access public
* @return void
*/
public function copyPriv(int $fromGroupID, int $toGroupID)
{
$privs = $this->dao->select('*')->from(TABLE_GROUPPRIV)->where('`group`')->eq($fromGroupID)->fetchAll();
foreach($privs as $key => $priv)
{
$privs[$key]->group = $toGroupID;
}
$this->insertPrivs($privs);
}
/**
* 复制分组的成员。
* Copy user.
*
* @param int $fromGroup
* @param int $toGroup
* @access public
* @return void
*/
public function copyUser($fromGroupID, $toGroupID)
{
$users = $this->dao->select('*')->from(TABLE_USERGROUP)->where('`group`')->eq($fromGroupID)->fetchAll();
foreach($users as $user)
{
$user->group = $toGroupID;
$this->dao->insert(TABLE_USERGROUP)->data($user, 'id')->exec();
}
}
/**
* 获取分组列表。
* Get group lists.
*
* @param int $projectID
* @access public
* @return array
*/
public function getList(int $projectID = 0)
{
return $this->dao->select('*')->from(TABLE_GROUP)
->where('project')->eq($projectID)
->beginIF($this->config->vision)->andWhere('vision')->eq($this->config->vision)->fi()
->orderBy('id')
->fetchAll();
}
/**
* 获取分组。
* Get group pairs.
*
* @param int $projectID
* @access public
* @return array
*/
public function getPairs(int $projectID = 0)
{
return $this->dao->select('id, name')->from(TABLE_GROUP)
->where('project')->eq($projectID)
->andWhere('vision')->eq($this->config->vision)
->orderBy('id')->fetchPairs();
}
/**
* 获取一个分组。
* Get group by id.
*
* @param int $groupID
* @access public
* @return object
*/
public function getByID(int $groupID)
{
$group = $this->dao->findById($groupID)->from(TABLE_GROUP)->fetch();
if(!$group) return null;
if($group->acl) $group->acl = json_decode($group->acl, true);
if(!isset($group->acl) || !is_array($group->acl)) $group->acl = array();
return $group;
}
/**
* 获取用户的所有分组。
* Get group by account.
*
* @param string $account
* @param bool $allVision
* @access public
* @return array
*/
public function getByAccount(string $account, bool $allVision = false)
{
return $this->dao->select('t2.*')->from(TABLE_USERGROUP)->alias('t1')
->leftJoin(TABLE_GROUP)->alias('t2')
->on('t1.`group` = t2.id')
->where('t1.account')->eq($account)
->andWhere('t2.project')->eq(0)
->beginIF(!$allVision)->andWhere('t2.vision')->eq($this->config->vision)->fi()
->fetchAll('id');
}
/**
* 获取多个分组包含的所有用户。
* Get the accounts in the groups.
*
* @param array $groupIdList
* @access public
* @return array
*/
public function getGroupAccounts(array $groupIdList = array())
{
$groupIdList = array_filter($groupIdList);
if(empty($groupIdList)) return array();
return $this->dao->select('account')->from(TABLE_USERGROUP)->where('`group`')->in($groupIdList)->fetchPairs('account');
}
/**
* 获取一个分组的权限列表。
* Get privileges of a groups.
*
* @param int $groupID
* @access public
* @return array
*/
public function getPrivs(int $groupID)
{
$privs = array();
$stmt = $this->dao->select('module, method')->from(TABLE_GROUPPRIV)->where('`group`')->eq($groupID)->orderBy('module')->query();
while($priv = $stmt->fetch()) $privs[$priv->module][$priv->method] = $priv->method;
return $privs;
}
/**
* 获取一个分组下的用户Pairs。
* Get user pairs of a group.
*
* @param int $groupID
* @access public
* @return array
*/
public function getUserPairs(int $groupID)
{
return $this->dao->select('t2.account, t2.realname')
->from(TABLE_USERGROUP)->alias('t1')
->leftJoin(TABLE_USER)->alias('t2')->on('t1.account = t2.account')
->where('`group`')->eq((int)$groupID)
->beginIF($this->config->vision)->andWhere("CONCAT(',', visions, ',')")->like("%,{$this->config->vision},%")->fi()
->andWhere('t2.deleted')->eq(0)
->orderBy('t2.account')
->fetchPairs();
}
/**
* 获取系统内权限分组的成员信息。
* Get all group members.
*
* @access public
* @return array
*/
public function getAllGroupMembers(): array
{
/* Get normal group members. */
$memberGroup = $this->dao->select('t1.`group` as `group`, t2.account, t2.realname')
->from(TABLE_USERGROUP)->alias('t1')
->leftJoin(TABLE_USER)->alias('t2')->on('t1.account = t2.account')
->where('t2.deleted')->eq(0)
->beginIF($this->config->vision)->andWhere("CONCAT(',', visions, ',')")->like("%,{$this->config->vision},%")->fi()
->orderBy('t2.account')
->fetchAll();
$groupMembers = array();
foreach($memberGroup as $member)
{
if(!isset($groupMembers[$member->group])) $groupMembers[$member->group] = array();
$groupMembers[$member->group][$member->account] = $member->realname;
}
/* Get project admin memebers. */
$projectAdmins = $this->dao->select('t1.account, t2.realname')->from(TABLE_PROJECTADMIN)->alias('t1')->leftJoin(TABLE_USER)->alias('t2')->on('t1.account = t2.account')->fetchPairs();
$adminGroupID = $this->dao->select('id')->from(TABLE_GROUP)->where('role')->eq('projectAdmin')->fetch('id');
$groupMembers[$adminGroupID] = $projectAdmins;
return $groupMembers;
}
/**
* 为项目管理员分组展示项目集、项目、产品、执行。
* Get object for manage admin group.
*
* @access public
* @return void
*/
public function getObjectForAdminGroup()
{
$objects = $this->dao->select('id, name, path, type, project, grade, parent')->from(TABLE_PROJECT)
->where('vision')->eq($this->config->vision)
->andWhere('type')->ne('program')
->andWhere('deleted')->eq(0)
->fetchAll('id');
$projects = array();
$executions = array();
foreach($objects as $object)
{
$type = $object->type;
$path = explode(',', trim($object->path, ','));
$topID = $path[0];
if($type == 'project')
{
if($topID != $object->id) $object->name = isset($objects[$topID]) ? $objects[$topID]->name . '/' . $object->name : $object->name;
$projects[$object->id] = $object->name;
}
else
{
if($object->grade == 2)
{
unset($objects[$object->parent]);
unset($executions[$object->parent]);
}
$object->name = isset($objects[$object->project]) ? $objects[$object->project]->name . '/' . $object->name : $object->name;
$executions[$object->id] = $object->name;
}
}
$programs = $this->getProgramsForAdminGroup();
$products = $this->getProductsForAdminGroup($programs);
return array($programs, $projects, $products, $executions);
}
/**
* 为项目管理员分组展示项目集。
* Get programs for admin group.
*
* @access protected
* @return array
*/
protected function getProgramsForAdminGroup()
{
$isAdmin = $this->app->user->admin;
/* Get the list of program sets under administrator permission. */
if(!$this->app->user->admin) $this->app->user->admin = true;
$programs = $this->loadModel('program')->getParentPairs('', '', false);
if(!$isAdmin) $this->app->user->admin = false;
return $programs;
}
/**
* 为项目管理员分组展示产品列表。
* Get products for admin group.
*
* @param array $programs
* @access protected
* @return array
*/
protected function getProductsForAdminGroup($programs)
{
$products = array();
$productList = $this->dao->select('id, name, program')->from(TABLE_PRODUCT)
->where('vision')->eq($this->config->vision)
->andWhere('deleted')->eq(0)
->andWhere('shadow')->eq(0)
->fetchAll('id');
foreach($productList as $id => $product)
{
if(isset($programs[$product->program]) and $this->config->systemMode == 'ALM') $product->name = $programs[$product->program] . '/' . $product->name;
$products[$product->id] = $product->name;
}
return $products;
}
/**
* 获取项目管理员。
* Get project admins for manage project admin.
*
* @access public
* @return array
*/
public function getProjectAdmins()
{
$admins = $this->dao->select('*')->from(TABLE_PROJECTADMIN)->fetchGroup('group', 'account');
$projectAdmins = array();
foreach($admins as $adminGroup)
{
if(!empty($adminGroup))
{
$accounts = implode(',', array_keys($adminGroup));
if(isset($projectAdmins[$accounts]))
{
$adminGroup = current($adminGroup);
$projectAdmins[$accounts]->programs .= ',' . $adminGroup->programs;
$projectAdmins[$accounts]->projects .= ',' . $adminGroup->projects;
$projectAdmins[$accounts]->products .= ',' . $adminGroup->products;
$projectAdmins[$accounts]->executions .= ',' . $adminGroup->executions;
}
else
{
$projectAdmins[$accounts] = current($adminGroup);
}
}
}
return $projectAdmins;
}
/**
* Get admins by object id list.
*
* @param array $idList
* @param string $field
* @access public
* @return array
*/
public function getAdmins(array $idList, string $field = 'programs'): array
{
$objects = array();
foreach($idList as $id)
{
$objects[$id] = $this->dao->select('DISTINCT account')->from(TABLE_PROJECTADMIN)
->where("CONCAT(',', $field, ',')")->like("%,$id,%")
->orWhere($field)->eq('all')
->fetchPairs();
}
return $objects;
}
/**
* 删除分组。
* Remove group.
*
* @param int $groupID
* @access public
* @return void
*/
public function remove(int $groupID)
{
$this->dao->delete()->from(TABLE_GROUP)->where('id')->eq($groupID)->exec();
$this->dao->delete()->from(TABLE_USERGROUP)->where('`group`')->eq($groupID)->exec();
$this->dao->delete()->from(TABLE_GROUPPRIV)->where('`group`')->eq($groupID)->exec();
}
/**
* Insert privs.
*
* @param array $privs
* @access protected
* @return bool
*/
public function insertPrivs(array $privs)
{
$groups = array();
foreach($privs as $priv) $groups[$priv->group] = $priv->group;
$privMap = array();
$privList = $this->dao->select('`group`,module,method')->from(TABLE_GROUPPRIV)->where('group')->in($groups)->fetchAll();
foreach($privList as $priv) $privMap[$priv->group . '-' . $priv->module . '-' . $priv->method] = true;
foreach($privs as $priv)
{
if(!isset($privMap[$priv->group . '-' . $priv->module . '-' . $priv->method]))
{
$this->dao->insert(TABLE_GROUPPRIV)->data($priv, 'id')->exec();
}
}
return true;
}
/**
* 更新视野权限。
* Update view priv.
*
* @param int $groupID
* @param array $actions
* @access public
* @return bool
*/
public function updateView(int $groupID, array $actions)
{
/* 如果产品不为空,需要将影子产品追加上。Add shadow productID when select noProduct project or execution. */
if(($actions['projects'] || $actions['sprints']) && isset($actions['products']))
{
/* Get all noProduct projects and executions . */
$noProductList = $this->loadModel('project')->getNoProductList();
$shadowProductIDList = $this->dao->select('id')->from(TABLE_PRODUCT)->where('shadow')->eq(1)->fetchPairs();
$noProductObjects = array_merge($actions['projects'], $actions['sprints']);
foreach($noProductObjects as $objectID)
{
if(isset($noProductList[$objectID])) $actions['products'][] = $noProductList[$objectID]->product;
}
}
/* 设置views。 Set views. */
if(!$actions['actionallchecker'])
{
$actions['views'] = empty($actions['views']) ? array() : array_keys($actions['views']);
$actions['views'] = array_combine($actions['views'], $actions['views']);
if(!isset($actions['actions'])) $actions['actions'] = array();
if(isset($actions['actions']['project']['started'])) $actions['actions']['project']['syncproject'] = 'syncproject';
if(isset($actions['actions']['execution']['started'])) $actions['actions']['execution']['syncexecution'] = 'syncexecution';
$dynamic = array();
foreach($actions['actions'] as $moduleName => $moduleActions)
{
$groupName = $moduleName;
if(isset($this->lang->navGroup->$moduleName)) $groupName = $this->lang->navGroup->$moduleName;
if($moduleName == 'case') $groupName = $this->lang->navGroup->testcase;
if($groupName != 'my' and !isset($actions['views'][$groupName])) continue;
$moduleActions = array_keys($moduleActions);
$dynamic[$moduleName] = array_combine($moduleActions, $moduleActions);
}
$actions['actions'] = $dynamic;
}
$actions = empty($actions) ? '' : json_encode($actions);
$this->dao->update(TABLE_GROUP)->set('acl')->eq($actions)->where('id')->eq($groupID)->exec();
return !dao::isError();
}
/**
* 按分组维护权限。
* Update privilege of a group.
*
* @param int $groupID
* @param string $nav
* @param string $version
* @access public
* @return bool
*/
public function updatePrivByGroup(int $groupID, string $nav, string $version = '')
{
/* Delete old. */
$privs = array_keys($this->getPrivsByNav($nav, $version));
$this->dao->delete()->from(TABLE_GROUPPRIV)
->where('`group`')->eq($groupID)
->beginIF(!empty($nav))->andWhere("CONCAT(module, '-', method)")->in($privs)->fi()
->exec();
$data = new stdclass();
$data->group = $groupID;
$data->module = 'index';
$data->method = 'index';
$this->dao->replace(TABLE_GROUPPRIV)->data($data)->exec();
/* Insert new. */
if($this->post->actions)
{
$dependPrivs = array();
foreach($this->config->group->package as $packageCode => $packageData)
{
if(!isset($packageData->privs)) continue;
foreach($packageData->privs as $privCode => $priv)
{
if(isset($priv['depend'])) $dependPrivs[$privCode] = $priv['depend'];
}
}
$insertPrivs = array();
$insertPrivKeys = array();
foreach($this->post->actions as $moduleName => $moduleActions)
{
if(empty($moduleName) or empty($moduleActions)) continue;
foreach($moduleActions as $actionName)
{
$data = new stdclass();
$data->group = $groupID;
$data->module = $moduleName;
$data->method = $actionName;
$priKey = "{$moduleName}-{$actionName}";
$insertPrivs[$priKey] = $data;
$insertPrivKeys[$priKey] = $priKey;
}
}
$insertDependPrivs = $this->processDepends($dependPrivs, $insertPrivKeys, $insertPrivKeys);
foreach($insertDependPrivs as $priKey)
{
if(isset($insertPrivs[$priKey])) continue;
list($moduleName, $actionName) = explode('-', $priKey);
$data = new stdclass();
$data->group = $groupID;
$data->module = $moduleName;
$data->method = $actionName;
$insertPrivs[$priKey] = $data;
}
$this->insertPrivs($insertPrivs);
return count($insertDependPrivs) != count($insertPrivKeys);
}
return true;
}
/**
* 按模块维护权限。
* Update privilege by module.
*
* @access public
* @return void
*/
public function updatePrivByModule()
{
if($this->post->module == false || array_filter($this->post->actions) == false || array_filter($this->post->groups) == false) return false;
$privs = array();
foreach($this->post->actions as $action)
{
if(!$action) continue;
list($module, $method) = explode('-', $action);
foreach($this->post->groups as $group)
{
$data = new stdclass();
$data->group = $group;
$data->module = $module;
$data->method = $method;
$privs[] = $data;
}
}
return $this->insertPrivs($privs);
}
/**
* 更新用户。
* Update users.
*
* @param int $groupID
* @access public
* @return bool
*/
public function updateUser(int $groupID): bool
{
$members = $this->post->members ? $this->post->members : array();
$groupUsers = $this->dao->select('account')->from(TABLE_USERGROUP)->where('`group`')->eq($groupID)->fetchPairs('account');
$newUsers = array_diff($members, $groupUsers);
$delUsers = array_diff($groupUsers, $members);
if(!empty($delUsers)) $this->dao->delete()->from(TABLE_USERGROUP)->where('`group`')->eq($groupID)->andWhere('account')->in($delUsers)->exec();
if(empty($newUsers)) return !dao::isError();
$data = new stdclass();
$data->group = $groupID;
$data->project = '';
foreach($newUsers as $account)
{
$data->account = $account;
$this->dao->insert(TABLE_USERGROUP)->data($data)->exec();
}
return !dao::isError();
}
/**
* 更新项目管理员。
* Update project admins.
*
* @param array $formData
* @access public
* @return void
*/
public function updateProjectAdmin(array $formData)
{
$allUsers = $this->dao->select('account')->from(TABLE_PROJECTADMIN)->fetchPairs();
$this->dao->delete()->from(TABLE_PROJECTADMIN)->exec();
$noProductList = $this->loadModel('project')->getNoProductList();
$shadowProductIDList = $this->dao->select('id')->from(TABLE_PRODUCT)->where('shadow')->eq(1)->fetchPairs();
foreach($formData as $lineID => $data)
{
if(!in_array('all', $data['product']))
{
/* 无产品项目的隐藏产品需要添加到product里。 Append products of 'No Product' project,execution. */
if($data['project'] || $data['execution'])
{
$objects = array_merge($data['project'], $data['execution']);
foreach($objects as $objectID)
{
if(isset($noProductList[$objectID])) $data['product'][] = $noProductList[$objectID]->product;
}
}
if((in_array('all', $data['execution']) || in_array('all', $data['project']))) $data['product'] = array_merge($data['product'], $shadowProductIDList);
}
foreach($data['accounts'] as $account)
{
if(!$account) continue;
$projectAdmin = new stdclass();
$projectAdmin->group = $lineID;
$projectAdmin->account = $account;
$projectAdmin->programs = implode(',', $data['program']);
$projectAdmin->projects = implode(',', $data['project']);
$projectAdmin->products = implode(',', $data['product']);
$projectAdmin->executions = implode(',', $data['execution']);
$this->dao->replace(TABLE_PROJECTADMIN)->data($projectAdmin)->exec();
$allUsers[$account] = $account;
}
}
$this->loadModel('user');
foreach($allUsers as $account)
{
if($account) $this->user->computeUserView($account, true);
}
return !dao::isError();
}
/**
* resource排序。
* Sort resource.
*
* @access public
* @return void
*/
public function sortResource()
{
$resources = $this->lang->resource;
$this->lang->resource = new stdclass();
/* sort moduleOrder. */
ksort($this->lang->moduleOrder, SORT_ASC);
foreach($this->lang->moduleOrder as $moduleName)
{
if(!isset($resources->$moduleName)) continue;
$resource = $resources->$moduleName;
unset($resources->$moduleName);
$this->lang->resource->$moduleName = $resource;
}
foreach($resources as $key => $resource)
{
$this->lang->resource->$key = $resource;
}
/* sort methodOrder. */
foreach($this->lang->resource as $moduleName => $resources)
{
$resources = (array)$resources;
$tmpResources = new stdclass();
if(isset($this->lang->$moduleName->methodOrder))
{
ksort($this->lang->$moduleName->methodOrder, SORT_ASC);
foreach($this->lang->$moduleName->methodOrder as $key)
{
if(isset($resources[$key]))
{
$tmpResources->$key = $resources[$key];
unset($resources[$key]);
}
}
if($resources)
{
foreach($resources as $key => $resource)
{
$tmpResources->$key = $resource;
}
}
$this->lang->resource->$moduleName = $tmpResources;
unset($tmpResources);
}
}
}
/**
* 判断分组操作是否可点击。
* Judge an action is clickable or not.
*
* @param object $group
* @param string $action
* @static
* @access public
* @return bool
*/
public static function isClickable(object $group, string $action): bool
{
$action = strtolower($action);
if($group->role == 'projectAdmin' && $action != 'manageprojectadmin') return false;
if($action == 'manageprojectadmin' && $group->role != 'projectAdmin') return false;
if($action == 'manageview' && $group->role == 'limited') return false;
if($action == 'copy' && $group->role == 'limited') return false;
return true;
}
/**
* 加载resource的语言配置。
* Load language of resource.
*
* @access public
* @return void
*/
public function loadResourceLang(): void
{
foreach($this->lang->resource as $moduleName => $action) $this->app->loadLang($moduleName);
$this->app->loadLang('doc');
$this->app->loadLang('api');
$this->lang->custom->common = $this->lang->group->config;
$this->lang->doc->common = $this->lang->doc->manage;
$this->lang->api->common = $this->lang->api->manage;
if(($this->config->edition == 'max' or $this->config->edition == 'ipd') and $this->config->vision == 'rnd' and isset($this->lang->baseline)) $this->lang->baseline->common = $this->lang->group->docTemplate;
}
/**
* 处理权限依赖关系
* Process circular dependency.
*
* @param array $depends
* @param array $privs
* @param array $excludes
* @param array $processedPrivs
* @access protected
* @return array
*/
protected function processDepends(array $depends, array $privs, array $excludes, array $processedPrivs = array()): array
{
foreach($privs as $priv)
{
if(!isset($depends[$priv]) || isset($processedPrivs[$priv])) continue;
/* 不重复处理权限,防止出现死循环。Avoid the infinite loop. */
$processedPrivs[$priv] = true;
foreach($depends[$priv] as $dependPriv)
{
if(isset($privs[$dependPriv]) || in_array($dependPriv, $excludes)) continue;
$privs[$dependPriv] = $dependPriv;
$dependPrivs = $this->processDepends($depends, zget($depends, $dependPriv, array()), $excludes, $processedPrivs);
foreach($dependPrivs as $depend)
{
if(!in_array($depend, $excludes)) $privs[$depend] = $depend;
}
}
}
return $privs;
}
/**
* 检查subset是否属于该nav。
* Check nav have subset.
*
* @param string $nav
* @param string $subset
* @access protected
* @return bool
*/
protected function checkNavSubset(string $nav, string $subset): bool
{
if(empty($nav)) return true;
if($nav == 'general') return !isset($this->config->group->subset->$subset) || !isset($this->config->group->subset->$subset->nav) || $this->config->group->subset->$subset->nav == 'general';
return isset($this->config->group->subset->$subset)
&& isset($this->config->group->subset->$subset->nav)
&& $this->config->group->subset->$subset->nav == $nav;
}
/**
* Get priv list by nav.
*
* @param string $nav
* @param string $version
* @access public
* @return array
*/
public function getPrivsByNav(string $nav = '', string $version = ''): array
{
$privList = array();
$allPrivs = array();
/* Filter privs equal or greater than this version.*/
if($version) $versionPrivs = $this->getPrivsAfterVersion($version);
$hiddenHost = $this->loadModel('zahost')->hiddenHost();
/* Privs in package. */
foreach($this->config->group->package as $packageCode => $packageData)
{
if(!isset($packageData->privs)) continue;
$sortPriv = array();
foreach($packageData->privs as $privCode => $priv)
{
list($moduleName, $methodName) = explode('-', $privCode);
$allPrivs[$privCode] = $privCode;
if($hiddenHost && $moduleName == 'zahost') continue;
if($hiddenHost && $moduleName == 'zanode' && !in_array($methodName, $this->config->group->showNodePriv)) continue;
if(!$this->config->inQuickon && !$this->config->inCompose && in_array("{$moduleName}-{$methodName}", $this->config->group->hiddenPriv)) continue;
if(strpos(',' . $priv['edition'] . ',', ',' . $this->config->edition . ',') === false) continue;
if(strpos(',' . $priv['vision'] . ',', ',' . $this->config->vision . ',') === false) continue;
if(!$this->checkNavSubset($nav, $packageData->subset)) continue;
/* If version is selected, only show privs before the version. */
if(!empty($version) and strpos($versionPrivs, ",$privCode,") === false) continue;
/* Add methods in workflow menus, remove privs unused in the edition. */
if(isset($this->lang->$moduleName->menus) && isset($this->lang->$moduleName->menus[$methodName]))
{
$privName = $this->lang->$moduleName->menus[$methodName];
}
else
{
if(!isset($this->lang->resource->$moduleName) || !isset($this->lang->resource->$moduleName->$methodName)) continue;
$methodLang = $this->lang->resource->$moduleName->$methodName;
if(!isset($this->lang->$moduleName->$methodLang))
{
$this->app->loadLang($moduleName);
if($moduleName == 'requirement') $this->app->loadLang('story');
}
$privName = isset($this->lang->$moduleName) && isset($this->lang->$moduleName->$methodLang) ? $this->lang->$moduleName->$methodLang : $privCode;
}
$privData = (object)array('code' => $privCode, 'subset' => $packageData->subset, 'package' => $packageCode, 'module' => $moduleName, 'method' => $methodName, 'selected' => false, 'name' => $privName);
/* 将order作为键方便排序。 */
if(!empty($priv['order']) && !isset($sortPriv[$priv['order']]))
{
$sortPriv[$priv['order']] = $privData;
}
else
{
$sortPriv[] = $privData;
}
}
/* 以order排序后再放入privList数组。 */
ksort($sortPriv);
foreach($sortPriv as $priv) $privList[$priv->code] = $priv;
}
return $privList;
}
/**
* Get privs list by group.
*
* @param int $groupID
* @access public
* @return array
*/
public function getPrivsByGroup(int $groupID): array
{
return $this->dao->select("CONCAT(module, '-', method) AS action")->from(TABLE_GROUPPRIV)->where('`group`')->eq($groupID)->fetchPairs();
}
/**
* AJAX: Get privs by parents.
*
* @param string $selectedSubset
* @param string $selectedPackages
* @access public
* @return array
*/
public function getPrivsByParents(string $selectedSubset, string $selectedPackages = ''): array
{
$allPrivs = array();
$privs = array();
/* Privs in package. */
foreach($this->config->group->package as $packageCode => $packageData)
{
if(!isset($packageData->privs)) continue;
foreach($packageData->privs as $privCode => $priv)
{
list($moduleName, $methodName) = explode('-', $privCode);
/* Remove privs unused in the edition. */
if(isset($this->lang->$moduleName->menus) && isset($this->lang->$moduleName->menus[$methodName]))
{
$privName = $this->lang->$moduleName->menus[$methodName];
}
else
{
if(!isset($this->lang->resource->$moduleName) || !isset($this->lang->resource->$moduleName->$methodName)) continue;
$methodLang = $this->lang->resource->$moduleName->$methodName;
if(!isset($this->lang->$moduleName->$methodLang))
{
$this->app->loadLang($moduleName);
if($moduleName == 'requirement') $this->app->loadLang('story');
}
$privName = isset($this->lang->$moduleName) && isset($this->lang->$moduleName->$methodLang) ? $this->lang->$moduleName->$methodLang : "$moduleName-$methodName";
}
$allPrivs[$privCode] = $privCode;
$subset = $packageData->subset;
if($subset !== $selectedSubset) continue;
if($selectedPackages && strpos($selectedPackages, "|$packageCode|") === false) continue;
$privs[$privCode] = $privName;
}
}
return $privs;
}
/**
* Get privs after version
*
* @param string $version
* @access public
* @return string
*/
public function getPrivsAfterVersion(string $version): string
{
$realVersion = str_replace('_', '.', $version);
$changelog = array();
foreach($this->lang->changelog as $currentVersion => $currentChangeLog)
{
if(version_compare($currentVersion, $realVersion, '>=')) $changelog[] = join(',', $currentChangeLog);
}
$versionPrivs = ',' . join(',', $changelog) . ',';
return $versionPrivs;
}
/**
* Get related privs.
*
* @param array $allPrivList
* @param array $selectedPrivList
* @param array $recommendSelect
* @access public
* @return array
*/
public function getRelatedPrivs(array $allPrivList, array $selectedPrivList, array $recommendSelect = array()): array
{
$this->loadResourceLang();
$depends = array();
$privSubsets = array();
$relatedPrivs = array('depend' => array(), 'recommend' => array());
foreach($this->config->group->package as $packagePage => $package)
{
if(!isset($package->privs)) continue;
foreach($package->privs as $privCode => $priv)
{
$privSubsets[$privCode] = $package->subset;
foreach(array('depend', 'recommend') as $type)
{
/* Show related privs when select. */
if($type == 'recommend' && in_array($privCode, $recommendSelect)) $relatedPrivs[$type][$privCode] = $privCode;
if(!in_array($privCode, $selectedPrivList) || !isset($priv[$type])) continue;
foreach($priv[$type] as $code => $relatedPriv)
{
if(!in_array($relatedPriv, $selectedPrivList) && in_array($relatedPriv, $allPrivList))
{
$relatedPrivs[$type][$relatedPriv] = $relatedPriv;
if($type == 'depend') $depends[$privCode][$code] = $relatedPriv;
}
}
}
}
}
/* Process circular dependency. */
$relatedPrivs['depend'] = $this->processDepends($depends, $relatedPrivs['depend'], $selectedPrivList);
$subsetPrivs = array('depend' => array(), 'recommend' => array());
foreach(array('depend', 'recommend') as $type)
{
foreach($relatedPrivs[$type] as $relatedPriv)
{
if($type == 'recommend' && isset($relatedPrivs['depend'][$relatedPriv])) continue; // Don't show depend privs to recommend.
$subsetName = $privSubsets[$relatedPriv];
$subsetTitle = isset($this->lang->$subsetName) && isset($this->lang->$subsetName->common) ? $this->lang->$subsetName->common : $subsetName;
if(!isset($subsetPrivs[$type][$subsetName])) $subsetPrivs[$type][$subsetName] = array('id' => $subsetName, 'text' => $subsetTitle, 'children' => array());
list($moduleName, $methodName) = explode('-', $relatedPriv);
if(!isset($this->lang->resource->$moduleName->$methodName)) continue;
$method = $this->lang->resource->$moduleName->$methodName;
if(!isset($this->lang->$moduleName->$method)) $this->app->loadLang($moduleName);
$subsetPrivs[$type][$subsetName]['children'][] = array('id' => $relatedPriv, 'data-module' => $moduleName, 'data-method' => $methodName, 'subset' => $subsetName, 'text' => $this->lang->$moduleName->$method, 'data-id' => $relatedPriv, 'title' => $this->lang->$moduleName->$method);
}
}
return array('depend' => array_values($subsetPrivs['depend']), 'recommend' => array_values($subsetPrivs['recommend']));
}
}