|
|
<?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; } }
|