You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
166 lines
7.9 KiB
166 lines
7.9 KiB
<?php
|
|
namespace backend\logic;
|
|
|
|
use ReflectionClass;
|
|
use ReflectionException;
|
|
use ReflectionMethod;
|
|
use yii;
|
|
|
|
class PermissionManager
|
|
{
|
|
/**
|
|
* 获取app的已做标记控制器的权限
|
|
* DESCRIBE 控制器描述,只有控制器的注释添加了该描述,才会自动匹配该控制器;使用例子:@DESCRIBE {controllerDescribe} DESCRIBE
|
|
* ACTION 方法描述,只有控制器下action方法的注释添加了该描述,才会自动匹配该action方法;使用例子:@ACTION {actionDescribe} ACTION
|
|
* 匹配控制器中actions的方法,需要添加id参数并且在标明含义,例子:
|
|
* '{actionName}' => [
|
|
* 'class' => 'xxx\xxx\xxx',
|
|
* 'id' => '{actionDescribe}'
|
|
* ]
|
|
* @return array 返回已匹配到的权限。返回例子:[["{controllerDescribe}"=>["{actionDescribe}"=>"action route"]]]
|
|
* @throws yii\base\InvalidConfigException
|
|
* @throws ReflectionException
|
|
*/
|
|
public static function getAppPermission()
|
|
{
|
|
$permission = [];
|
|
$permission = self::getControllersAndActions($permission); //获取该app的所有controller权限
|
|
$permission = self::getModuleControllerAndAction($permission); //获取该app引用module的所有controller权限
|
|
return $permission;
|
|
}
|
|
|
|
/**
|
|
* 获取app下controller已标记的action方法权限
|
|
* 这个方法先是获取该app下controller的路径,控制器的命名空间,然后匹配该路径下面的所有控制器文件
|
|
* 截取控制器文件的控制器基础名称,转换为相应url规则名称,拼接为相应类名
|
|
* 根据控制器id,通过[[Module::createControllerByID]]方法实例化该控制器,最后通过[[PermissionManager::constructingPermissionArray]]获取所有已标记的权限
|
|
* @param array $permission 权限数组
|
|
* @return array 权限数组
|
|
* @throws yii\base\InvalidConfigException
|
|
* @throws ReflectionException
|
|
*/
|
|
private static function getControllersAndActions($permission = [])
|
|
{
|
|
$dir = Yii::$app->getControllerPath();
|
|
$nameSpace = Yii::$app->controllerNamespace . "\\";
|
|
$fileList = glob($dir."/*Controller.php");
|
|
foreach ($fileList as $file) {
|
|
$baseName = substr(basename($file), 0, -14);
|
|
|
|
//根据路由规则转换控制器名称
|
|
$name = strtolower(preg_replace('/(?<![A-Z])[A-Z]/', ' \0', $baseName));
|
|
$id = ltrim(str_replace(' ', '-', $name), '-');
|
|
|
|
$className = $nameSpace . $baseName . 'Controller';
|
|
$controller = Yii::$app->createControllerByID($id);
|
|
$permission = self::constructingPermissionArray($controller, $className, $permission);
|
|
}
|
|
return $permission;
|
|
}
|
|
|
|
/**
|
|
* 获取该app下关联module的已标记controller的权限
|
|
* 这个方法通过[[Module::getModules]]获取该app下关联的module并循环
|
|
* 去除gii和debug,通过[[Module::getModule]]获取子类module,获取命名空间,文件位置,然后匹配该路径下面的所有控制器文件
|
|
* 截取控制器文件的控制器基础名称,转换为相应url规则名称,拼接为相应类名
|
|
* 通过[[BaseYii::createObject]]实例化,最后通过[[PermissionManager::constructingPermissionArray]]获取所有已标记的权限
|
|
* @param array $permission 权限数组
|
|
* @return array 权限数组
|
|
* @throws yii\base\InvalidConfigException
|
|
* @throws ReflectionException
|
|
*/
|
|
private static function getModuleControllerAndAction($permission = [])
|
|
{
|
|
foreach (Yii::$app->getModules() as $id => $child) {
|
|
if(in_array($id, ['gii', 'debug'])) {
|
|
continue;
|
|
}
|
|
$module = Yii::$app->getModule($id);
|
|
$nameSpace = $module->controllerNamespace."\\";
|
|
$dir = $module->controllerPath;
|
|
$fileList = glob($dir."/*Controller.php");
|
|
foreach ($fileList as $file) {
|
|
$baseName = substr(basename($file), 0, -14);
|
|
$name = strtolower(preg_replace('/(?<![A-Z])[A-Z]/', ' \0', $baseName));
|
|
$id = $module->id.'/'.ltrim(str_replace(' ', '-', $name), '-');
|
|
$className = $nameSpace . $baseName . 'Controller';
|
|
$controller = Yii::createObject($className, [$id, $module]);
|
|
$permission = self::constructingPermissionArray($controller, $className, $permission);
|
|
}
|
|
}
|
|
return $permission;
|
|
}
|
|
|
|
/**
|
|
* 构建权限数组
|
|
* 根据类名,使用ReflectionClass方法获取该类的信息
|
|
* 通过该类的注释,判断是否存在DESCRIBE标记,以此判断是否要记录该类的权限
|
|
* 若存在标记,则通过[[PermissionManager::getActionsInController]]获取actions里面的方法权限数组,通过[[PermissionManager::getActionInController]]获取该类下面的action方法权限数组
|
|
* @param $controllerObject
|
|
* @param $className
|
|
* @param array $permission 权限数组
|
|
* @return array 权限数组
|
|
* @throws ReflectionException
|
|
*/
|
|
private static function constructingPermissionArray($controllerObject, $className, $permission = [])
|
|
{
|
|
$prefix = '/'.$controllerObject->id.'/';
|
|
$reflection = new ReflectionClass($className); //通过ReflectionClass方法获取该类的所有信息,包括参数方法等
|
|
$controllerComment = $reflection->getDocComment();
|
|
$controllerPregRes = preg_match("/(?<=@DESCRIBE ).*?(?= DESCRIBE)/", $controllerComment, $controllerDescribe);
|
|
if ($controllerPregRes) {
|
|
$permission = self::getActionsInController($controllerObject, $controllerDescribe, $prefix, $permission);
|
|
$permission = self::getActionInController($className, $prefix, $controllerDescribe, $permission);
|
|
}
|
|
return $permission;
|
|
}
|
|
|
|
/**
|
|
* 获取控制器类中actions的方法权限
|
|
* 根据实例化的控制器类,获取actions的方法并且循环,方法存在id这个参数,则记录
|
|
* 最后放回权限数组
|
|
* @param $controllerObject
|
|
* @param $controllerDescribe
|
|
* @param $prefix
|
|
* @param array $permission 权限数组
|
|
* @return array 权限数组
|
|
*/
|
|
private static function getActionsInController($controllerObject, $controllerDescribe, $prefix, $permission = [])
|
|
{
|
|
foreach ($controllerObject->actions() as $id => $item) {
|
|
if (isset($item['id'])) {
|
|
$permission[$controllerDescribe[0]][$item['id']] = $prefix . $id;
|
|
}
|
|
}
|
|
return $permission;
|
|
}
|
|
|
|
/**
|
|
* 获取控制器类中的action方法权限
|
|
* 通过ReflectionClass方法获取所有的action方法,若注释中存在ACTION标记,则记录
|
|
* @param $className
|
|
* @param $prefix
|
|
* @param $controllerDescribe
|
|
* @param array $permission 权限数组
|
|
* @return array 权限数组
|
|
* @throws ReflectionException
|
|
*/
|
|
private static function getActionInController($className, $prefix, $controllerDescribe, $permission = [])
|
|
{
|
|
$reflection = new ReflectionClass($className); //通过ReflectionClass方法获取该类的所有信息,包括参数方法等
|
|
foreach ($reflection->getMethods(ReflectionMethod::IS_PUBLIC) as $method) {
|
|
//action的注释
|
|
$actionComment = $method->getDocComment();
|
|
$actionPregRes = preg_match("/(?<=@ACTION ).*?(?= ACTION)/", $actionComment, $actionDescribe);
|
|
if ($actionPregRes) {
|
|
$actionName = $method->getName();
|
|
if ($actionName != 'actions' && strpos($actionName, 'action') === 0) {
|
|
$name = strtolower(preg_replace('/(?<![A-Z])[A-Z]/', ' \0', substr($actionName, 6)));
|
|
$id = $prefix . ltrim(str_replace(' ', '-', $name), '-');
|
|
$permission[$controllerDescribe[0]][$actionDescribe[0]] = $id;
|
|
}
|
|
}
|
|
}
|
|
return $permission;
|
|
}
|
|
}
|