1
This commit is contained in:
@@ -0,0 +1,460 @@
|
||||
<?php
|
||||
|
||||
namespace plugin\admin\app\controller;
|
||||
|
||||
use Cache;
|
||||
use Exception;
|
||||
use Illuminate\Support\Facades\Date;
|
||||
use plugin\admin\app\common\Auth;
|
||||
use plugin\admin\app\common\Tree;
|
||||
use plugin\admin\app\common\Util;
|
||||
use plugin\admin\app\model\AdminRole;
|
||||
use plugin\admin\app\model\AdminRule;
|
||||
use support\exception\BusinessException;
|
||||
use support\Request;
|
||||
use support\Response;
|
||||
use Throwable;
|
||||
|
||||
/**
|
||||
* 权限菜单
|
||||
*/
|
||||
class AdminRuleController extends Crud
|
||||
{
|
||||
/**
|
||||
* 不需要权限的方法
|
||||
*
|
||||
* @var string[]
|
||||
*/
|
||||
protected $noNeedAuth = ['get', 'permission'];
|
||||
|
||||
/**
|
||||
* @var AdminRule
|
||||
*/
|
||||
protected $model = null;
|
||||
|
||||
/**
|
||||
* 构造函数
|
||||
*/
|
||||
function __construct()
|
||||
{
|
||||
$this->model = new AdminRule;
|
||||
}
|
||||
|
||||
/**
|
||||
* 浏览
|
||||
* @return Response
|
||||
* @throws Throwable
|
||||
*/
|
||||
public function index(Request $request): Response
|
||||
{
|
||||
return view('admin_rule/index');
|
||||
}
|
||||
|
||||
/**
|
||||
* 格式化树
|
||||
* @param $items
|
||||
* @return Response
|
||||
*/
|
||||
protected function formatTree($items): Response
|
||||
{
|
||||
$format_items = [];
|
||||
//$primary_key = $this->model->getPk();
|
||||
$primary_key = $this->model->getPk();
|
||||
foreach ($items as $item) {
|
||||
$item->text = $item->title;
|
||||
//$item->value = (string)$item->$primary_key;
|
||||
$item->id = $item->$primary_key;
|
||||
$item->parent = $item->pid;
|
||||
if($item->pid == 0){
|
||||
$item->parent = '#';
|
||||
}
|
||||
unset($item->pid);
|
||||
$format_items[] = $item;
|
||||
}
|
||||
$tree = new Tree($format_items);
|
||||
return $this->success("操作成功", $tree->getTree());
|
||||
}
|
||||
|
||||
/**
|
||||
* 权限树形
|
||||
* @param Request $request
|
||||
* @return Response
|
||||
* @throws BusinessException
|
||||
*/
|
||||
public function roletree(Request $request): Response
|
||||
{
|
||||
[$where, $format, $limit, $field, $order] = $this->selectInput($request);
|
||||
$query = $this->doSelect($where, $field, $order);
|
||||
$methods = [
|
||||
'select' => 'formatSelect',
|
||||
'tree' => 'formatTree',
|
||||
'table_tree' => 'formatTableTree',
|
||||
'normal' => 'formatNormal',
|
||||
];
|
||||
$format = 'normal';
|
||||
$items = $query->field('id,title as text,pid as parent,"menu" as type')->select();
|
||||
/**
|
||||
* @var AdminRule $item
|
||||
*/
|
||||
foreach ($items as $key => $item) {
|
||||
$items[$key]->state = [
|
||||
"selected" => false,
|
||||
];
|
||||
if($items[$key]->parent == 0){
|
||||
$items[$key]->parent = '#';
|
||||
}
|
||||
};
|
||||
if (method_exists($this, "afterQuery")) {
|
||||
$items = call_user_func([$this, "afterQuery"], $items);
|
||||
}
|
||||
$format_function = $methods[$format] ?? 'formatNormal';
|
||||
|
||||
return call_user_func([$this, $format_function], $items, 0);
|
||||
}
|
||||
/**
|
||||
* 查询
|
||||
* @param Request $request
|
||||
* @return Response
|
||||
* @throws BusinessException
|
||||
*/
|
||||
public function select(Request $request): Response
|
||||
{
|
||||
[$where, $format, $limit, $field, $order] = $this->selectInput($request);
|
||||
$query = $this->doSelect($where, $field, $order);
|
||||
return $this->doFormat($query, $format, 'all');
|
||||
}
|
||||
/**
|
||||
* 刷新缓存
|
||||
* @param \support\Request $request
|
||||
* @return Response
|
||||
*/
|
||||
public function buildcache(Request $request){
|
||||
//缓存
|
||||
$list = $this->get($request)->rawBody();
|
||||
$list = json_decode($list,true);
|
||||
$fn = base_path() . '/plugin/admin/config/menu.php';
|
||||
file_put_contents($fn, "<?php \n return ".var_export($list['data'],true).';');
|
||||
return $this->success('ok');
|
||||
}
|
||||
/**
|
||||
* 获取菜单
|
||||
* @param Request $request
|
||||
* @return Response
|
||||
* @throws Exception
|
||||
*/
|
||||
function get(Request $request): Response
|
||||
{
|
||||
|
||||
$is_supper_admin = Auth::isSuperAdmin();
|
||||
if($is_supper_admin){
|
||||
$rules = ['*'];
|
||||
}else{
|
||||
$rules = $this->getRules(admin('roles'));
|
||||
}
|
||||
//return $this->success("操作成功", admin('roles'));
|
||||
$types = $request->get('type', '0,1');
|
||||
$types = is_string($types) ? explode(',', $types) : [0, 1];
|
||||
$items = AdminRule::order('weight', 'desc')->select();
|
||||
|
||||
$formatted_items = [];
|
||||
/**
|
||||
* @var AdminRule $item
|
||||
*/
|
||||
foreach ($items as $item) {
|
||||
$item['pid'] = (int)$item['pid'];
|
||||
$item['name'] = $item['title'];
|
||||
$item['value'] = $item['id'];
|
||||
$item['icon'] = $item->icon ? "{$item->icon}" : '';
|
||||
$formatted_items[] = $item;
|
||||
}
|
||||
|
||||
$tree = new Tree($formatted_items);
|
||||
$tree_items = $tree->getTree();
|
||||
// 超级管理员权限为 *
|
||||
if (!in_array('*', $rules)) {
|
||||
$this->removeNotContain($tree_items, 'id', $rules);
|
||||
}
|
||||
$this->removeNotContain($tree_items, 'type', $types);
|
||||
$menus = $this->empty_filter(Tree::arrayValues($tree_items));
|
||||
return $this->success("操作成功", $menus);
|
||||
}
|
||||
|
||||
private function empty_filter($menus)
|
||||
{
|
||||
return array_map(
|
||||
function ($menu) {
|
||||
if (isset($menu['children'])) {
|
||||
$menu['children'] = $this->empty_filter($menu['children']);
|
||||
}
|
||||
return $menu;
|
||||
},
|
||||
array_values(array_filter(
|
||||
$menus,
|
||||
function ($menu) {
|
||||
return $menu['type'] != 0 || isset($menu['children']) && count($this->empty_filter($menu['children'])) > 0;
|
||||
}
|
||||
))
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取权限
|
||||
* @param Request $request
|
||||
* @return Response
|
||||
* @throws Exception
|
||||
*/
|
||||
public function permission(Request $request): Response
|
||||
{
|
||||
$rules = $this->getRules(admin('roles'));
|
||||
// 超级管理员
|
||||
if (in_array('*', $rules)) {
|
||||
return $this->success("操作成功", ['*']);
|
||||
}
|
||||
$keys = AdminRule::whereIn('id', $rules)->column('key');
|
||||
$permissions = [];
|
||||
foreach ($keys as $key) {
|
||||
if (!$key = Util::controllerToUrlPath($key)) {
|
||||
continue;
|
||||
}
|
||||
$code = str_replace('/', '.', trim($key, '/'));
|
||||
$permissions[] = $code;
|
||||
}
|
||||
return $this->success("操作成功", $permissions);
|
||||
}
|
||||
|
||||
/**
|
||||
* 同步规则
|
||||
* @return void
|
||||
*/
|
||||
public function syncRules(): Response
|
||||
{
|
||||
//$items = $this->model->where('key', 'like', '%\\\\%')->get()->keyBy('key');
|
||||
$items = $this->model->whereLike('key', '%\\\\%')->select();
|
||||
$methods_in_db = [];
|
||||
$methods_in_files = [];
|
||||
/**
|
||||
* @var AdminRule $item
|
||||
*/
|
||||
foreach ($items as $item) {
|
||||
$class = $item->key;
|
||||
if (strpos($class, '@')) {
|
||||
$methods_in_db[$class] = $class;
|
||||
continue;
|
||||
}
|
||||
if (class_exists('\\plugin\\admin\\'.$class)) {
|
||||
$reflection = new \ReflectionClass('\\plugin\\admin\\'.$class);
|
||||
$properties = $reflection->getDefaultProperties();
|
||||
$no_need_auth = array_merge($properties['noNeedLogin'] ?? [], $properties['noNeedAuth'] ?? []);
|
||||
$class = str_replace('plugin\admin\\','',$reflection->getName());
|
||||
$pid = $item->id;
|
||||
$methods = $reflection->getMethods(\ReflectionMethod::IS_PUBLIC);
|
||||
foreach ($methods as $method) {
|
||||
$method_name = $method->getName();
|
||||
if (strtolower($method_name) === 'index' || strpos($method_name, '__') === 0 || in_array($method_name, $no_need_auth)) {
|
||||
continue;
|
||||
}
|
||||
$name = "$class@$method_name";
|
||||
|
||||
$methods_in_files[$name] = $name;
|
||||
$title = Util::getCommentFirstLine($method->getDocComment()) ?: $method_name;
|
||||
/**
|
||||
* @var AdminRule $menu
|
||||
*/
|
||||
$menu = $items[$name] ?? [];
|
||||
if ($menu) {
|
||||
if ($menu->title != $title) {
|
||||
AdminRule::where('key', $name)->update(['title' => $title]);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
if(!AdminRule::where('key', $name)->count('id')) {
|
||||
$menu = new AdminRule;
|
||||
$menu->pid = $pid;
|
||||
$menu->key = $name;
|
||||
$menu->title = $title;
|
||||
$menu->type = 2;
|
||||
$menu->save();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// 从数据库中删除已经不存在的方法
|
||||
$menu_names_to_del = array_diff($methods_in_db, $methods_in_files);
|
||||
if ($menu_names_to_del) {
|
||||
AdminRule::whereIn('key', $menu_names_to_del)->delete();
|
||||
}
|
||||
return $this->success("操作成功");
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询前置方法
|
||||
* @param Request $request
|
||||
* @return array
|
||||
* @throws BusinessException
|
||||
*/
|
||||
protected function selectInput(Request $request): array
|
||||
{
|
||||
[$where, $format, $limit, $field, $order] = parent::selectInput($request);
|
||||
// 允许通过type=0,1格式传递菜单类型
|
||||
$types = $request->get('type');
|
||||
if ($types && is_string($types)) {
|
||||
$where['type'] = ['symbol'=>'in', 'value1'=>explode(',', $types)];
|
||||
}
|
||||
// 默认weight排序
|
||||
if (!$field) {
|
||||
$field = 'weight';
|
||||
$order = 'desc';
|
||||
}
|
||||
return [$where, $format, $limit, $field, $order];
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加
|
||||
* @param Request $request
|
||||
* @return Response
|
||||
* @throws BusinessException|Throwable
|
||||
*/
|
||||
public function insert(Request $request): Response
|
||||
{
|
||||
if ($request->method() === 'GET') {
|
||||
$RuleList = $this->model->where('status',1)->order('id asc')->select();
|
||||
$tree = new Tree($RuleList);
|
||||
return view('admin_rule/update',[
|
||||
'RuleList' => $tree->getTree()
|
||||
]);
|
||||
}
|
||||
$data = $this->insertInput($request);
|
||||
if (empty($data['type'])) {
|
||||
$data['type'] = strpos($data['key'], '\\') ? 1 : 0;
|
||||
}
|
||||
$data['key'] = str_replace('\\\\', '\\', $data['key']);
|
||||
$key = $data['key'] ?? '';
|
||||
if ($this->model->where('key', $key)->count('id')) {
|
||||
return $this->fail("菜单标识 $key 已经存在");
|
||||
}
|
||||
$data['pid'] = empty($data['pid']) ? 0 : $data['pid'];
|
||||
$this->doInsert($data);
|
||||
return $this->success("操作成功");
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新
|
||||
* @param Request $request
|
||||
* @return Response
|
||||
* @throws BusinessException|Throwable
|
||||
*/
|
||||
public function update(Request $request): Response
|
||||
{
|
||||
if ($request->method() === 'GET') {
|
||||
$RuleList = $this->model->order('id asc')->select();
|
||||
$ids = Request()->get('ids');
|
||||
$tree = new Tree($RuleList);
|
||||
return view('admin_rule/update',[
|
||||
'RuleList' => $tree->getTree(),
|
||||
'row' => $this->model->where('id',$ids)->find()
|
||||
]);
|
||||
}
|
||||
[$id, $data] = $this->updateInput($request);
|
||||
if (!$row = $this->model->find($id)) {
|
||||
return $this->json(2, '记录不存在');
|
||||
}
|
||||
if (isset($data['pid'])) {
|
||||
$data['pid'] = $data['pid'] ?: 0;
|
||||
if ($data['pid'] == $row['id']) {
|
||||
return $this->json(2, '不能将自己设置为上级菜单');
|
||||
}
|
||||
}
|
||||
if (isset($data['key'])) {
|
||||
$data['key'] = str_replace('\\\\', '\\', $data['key']);
|
||||
}
|
||||
$this->doUpdate($id, $data);
|
||||
return $this->success("操作成功");
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除
|
||||
* @param Request $request
|
||||
* @return Response
|
||||
*/
|
||||
public function delete(Request $request): Response
|
||||
{
|
||||
$ids = $this->deleteInput($request);
|
||||
// 子规则一起删除
|
||||
$delete_ids = $children_ids = $ids;
|
||||
while($children_ids) {
|
||||
$children_ids = $this->model->whereIn('pid', $children_ids)->column('id');
|
||||
$delete_ids = array_merge($delete_ids, $children_ids);
|
||||
}
|
||||
$this->doDelete($delete_ids);
|
||||
return $this->success("操作成功");
|
||||
}
|
||||
|
||||
/**
|
||||
* 移除不包含某些数据的数组
|
||||
* @param $array
|
||||
* @param $key
|
||||
* @param $values
|
||||
* @return void
|
||||
*/
|
||||
protected function removeNotContain(&$array, $key, $values)
|
||||
{
|
||||
foreach ($array as $k => &$item) {
|
||||
if (!is_array($item)) {
|
||||
continue;
|
||||
}
|
||||
if (!$this->arrayContain($item, $key, $values)) {
|
||||
unset($array[$k]);
|
||||
} else {
|
||||
if (!isset($item['children'])) {
|
||||
continue;
|
||||
}
|
||||
$this->removeNotContain($item['children'], $key, $values);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断数组是否包含某些数据
|
||||
* @param $array
|
||||
* @param $key
|
||||
* @param $values
|
||||
* @return bool
|
||||
*/
|
||||
protected function arrayContain(&$array, $key, $values): bool
|
||||
{
|
||||
if (!is_array($array)) {
|
||||
return false;
|
||||
}
|
||||
if (isset($array[$key]) && in_array($array[$key], $values)) {
|
||||
return true;
|
||||
}
|
||||
if (!isset($array['children'])) {
|
||||
return false;
|
||||
}
|
||||
foreach ($array['children'] as $item) {
|
||||
if ($this->arrayContain($item, $key, $values)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取权限规则
|
||||
* @param $roles
|
||||
* @return array
|
||||
*/
|
||||
protected function getRules($roles): array
|
||||
{
|
||||
$rules_strings = $roles ? AdminRole::whereIn('id', $roles)->column('rules') : [];
|
||||
$rules = [];
|
||||
foreach ($rules_strings as $rule_string) {
|
||||
if (!$rule_string) {
|
||||
continue;
|
||||
}
|
||||
$rules = array_merge($rules, explode(',', $rule_string));
|
||||
}
|
||||
return $rules;
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user