226 lines
6.5 KiB
PHP
226 lines
6.5 KiB
PHP
|
<?php
|
|||
|
|
|||
|
namespace app\common\library;
|
|||
|
|
|||
|
use app\admin\model\AuthRule;
|
|||
|
use fast\Tree;
|
|||
|
use think\addons\Service;
|
|||
|
use think\Db;
|
|||
|
use think\Exception;
|
|||
|
use think\exception\PDOException;
|
|||
|
|
|||
|
class Menu
|
|||
|
{
|
|||
|
|
|||
|
/**
|
|||
|
* 创建菜单
|
|||
|
* @param array $menu
|
|||
|
* @param mixed $parent 父类的name或pid
|
|||
|
*/
|
|||
|
public static function create($menu = [], $parent = 0)
|
|||
|
{
|
|||
|
$old = [];
|
|||
|
self::menuUpdate($menu, $old, $parent);
|
|||
|
|
|||
|
//菜单刷新处理
|
|||
|
$info = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS, 2)[1];
|
|||
|
preg_match('/addons\\\\([a-z0-9]+)\\\\/i', $info['class'], $matches);
|
|||
|
if ($matches && isset($matches[1])) {
|
|||
|
Menu::refresh($matches[1], $menu);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
/**
|
|||
|
* 删除菜单
|
|||
|
* @param string $name 规则name
|
|||
|
* @return boolean
|
|||
|
*/
|
|||
|
public static function delete($name)
|
|||
|
{
|
|||
|
$ids = self::getAuthRuleIdsByName($name);
|
|||
|
if (!$ids) {
|
|||
|
return false;
|
|||
|
}
|
|||
|
AuthRule::destroy($ids);
|
|||
|
return true;
|
|||
|
}
|
|||
|
|
|||
|
/**
|
|||
|
* 启用菜单
|
|||
|
* @param string $name
|
|||
|
* @return boolean
|
|||
|
*/
|
|||
|
public static function enable($name)
|
|||
|
{
|
|||
|
$ids = self::getAuthRuleIdsByName($name);
|
|||
|
if (!$ids) {
|
|||
|
return false;
|
|||
|
}
|
|||
|
AuthRule::where('id', 'in', $ids)->update(['status' => 'normal']);
|
|||
|
return true;
|
|||
|
}
|
|||
|
|
|||
|
/**
|
|||
|
* 禁用菜单
|
|||
|
* @param string $name
|
|||
|
* @return boolean
|
|||
|
*/
|
|||
|
public static function disable($name)
|
|||
|
{
|
|||
|
$ids = self::getAuthRuleIdsByName($name);
|
|||
|
if (!$ids) {
|
|||
|
return false;
|
|||
|
}
|
|||
|
AuthRule::where('id', 'in', $ids)->update(['status' => 'hidden']);
|
|||
|
return true;
|
|||
|
}
|
|||
|
|
|||
|
/**
|
|||
|
* 升级菜单
|
|||
|
* @param string $name 插件名称
|
|||
|
* @param array $menu 新菜单
|
|||
|
* @return bool
|
|||
|
*/
|
|||
|
public static function upgrade($name, $menu)
|
|||
|
{
|
|||
|
$ids = self::getAuthRuleIdsByName($name);
|
|||
|
$old = AuthRule::where('id', 'in', $ids)->select();
|
|||
|
$old = collection($old)->toArray();
|
|||
|
$old = array_column($old, null, 'name');
|
|||
|
|
|||
|
Db::startTrans();
|
|||
|
try {
|
|||
|
self::menuUpdate($menu, $old);
|
|||
|
$ids = [];
|
|||
|
foreach ($old as $index => $item) {
|
|||
|
if (!isset($item['keep'])) {
|
|||
|
$ids[] = $item['id'];
|
|||
|
}
|
|||
|
}
|
|||
|
if ($ids) {
|
|||
|
//旧版本的菜单需要做删除处理
|
|||
|
$config = Service::config($name);
|
|||
|
$menus = $config['menus'] ?? [];
|
|||
|
$where = ['id' => ['in', $ids]];
|
|||
|
if ($menus) {
|
|||
|
//必须是旧版本中的菜单,可排除用户自主创建的菜单
|
|||
|
$where['name'] = ['in', $menus];
|
|||
|
}
|
|||
|
AuthRule::where($where)->delete();
|
|||
|
}
|
|||
|
|
|||
|
Db::commit();
|
|||
|
} catch (PDOException $e) {
|
|||
|
Db::rollback();
|
|||
|
return false;
|
|||
|
}
|
|||
|
|
|||
|
Menu::refresh($name, $menu);
|
|||
|
return true;
|
|||
|
}
|
|||
|
|
|||
|
/**
|
|||
|
* 刷新插件菜单配置缓存
|
|||
|
* @param string $name
|
|||
|
* @param array $menu
|
|||
|
*/
|
|||
|
public static function refresh($name, $menu = [])
|
|||
|
{
|
|||
|
if (!$menu) {
|
|||
|
// $menu为空时表示首次安装,首次安装需刷新插件菜单标识缓存
|
|||
|
$menuIds = Menu::getAuthRuleIdsByName($name);
|
|||
|
$menus = Db::name("auth_rule")->where('id', 'in', $menuIds)->column('name');
|
|||
|
} else {
|
|||
|
// 刷新新的菜单缓存
|
|||
|
$getMenus = function ($menu) use (&$getMenus) {
|
|||
|
$result = [];
|
|||
|
foreach ($menu as $index => $item) {
|
|||
|
$result[] = $item['name'];
|
|||
|
$result = array_merge($result, isset($item['sublist']) && is_array($item['sublist']) ? $getMenus($item['sublist']) : []);
|
|||
|
}
|
|||
|
return $result;
|
|||
|
};
|
|||
|
$menus = $getMenus($menu);
|
|||
|
}
|
|||
|
|
|||
|
//刷新新的插件核心菜单缓存
|
|||
|
Service::config($name, ['menus' => $menus]);
|
|||
|
}
|
|||
|
|
|||
|
/**
|
|||
|
* 导出指定名称的菜单规则
|
|||
|
* @param string $name
|
|||
|
* @return array
|
|||
|
*/
|
|||
|
public static function export($name)
|
|||
|
{
|
|||
|
$ids = self::getAuthRuleIdsByName($name);
|
|||
|
if (!$ids) {
|
|||
|
return [];
|
|||
|
}
|
|||
|
$menuList = [];
|
|||
|
$menu = AuthRule::getByName($name);
|
|||
|
if ($menu) {
|
|||
|
$ruleList = collection(AuthRule::where('id', 'in', $ids)->select())->toArray();
|
|||
|
$menuList = Tree::instance()->init($ruleList)->getTreeArray($menu['id']);
|
|||
|
}
|
|||
|
return $menuList;
|
|||
|
}
|
|||
|
|
|||
|
/**
|
|||
|
* 菜单升级
|
|||
|
* @param array $newMenu
|
|||
|
* @param array $oldMenu
|
|||
|
* @param int $parent
|
|||
|
* @throws Exception
|
|||
|
*/
|
|||
|
private static function menuUpdate($newMenu, &$oldMenu, $parent = 0)
|
|||
|
{
|
|||
|
if (!is_numeric($parent)) {
|
|||
|
$parentRule = AuthRule::getByName($parent);
|
|||
|
$pid = $parentRule ? $parentRule['id'] : 0;
|
|||
|
} else {
|
|||
|
$pid = $parent;
|
|||
|
}
|
|||
|
$allow = array_flip(['file', 'name', 'title', 'url', 'icon', 'condition', 'remark', 'ismenu', 'menutype', 'extend', 'weigh', 'status']);
|
|||
|
foreach ($newMenu as $k => $v) {
|
|||
|
$hasChild = isset($v['sublist']) && $v['sublist'];
|
|||
|
$data = array_intersect_key($v, $allow);
|
|||
|
$data['ismenu'] = $data['ismenu'] ?? ($hasChild ? 1 : 0);
|
|||
|
$data['icon'] = $data['icon'] ?? ($hasChild ? 'fa fa-list' : 'fa fa-circle-o');
|
|||
|
$data['pid'] = $pid;
|
|||
|
$data['status'] = $data['status'] ?? 'normal';
|
|||
|
if (!isset($oldMenu[$data['name']])) {
|
|||
|
$menu = AuthRule::create($data);
|
|||
|
} else {
|
|||
|
$menu = $oldMenu[$data['name']];
|
|||
|
//更新旧菜单
|
|||
|
AuthRule::update($data, ['id' => $menu['id']]);
|
|||
|
$oldMenu[$data['name']]['keep'] = true;
|
|||
|
}
|
|||
|
if ($hasChild) {
|
|||
|
self::menuUpdate($v['sublist'], $oldMenu, $menu['id']);
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
/**
|
|||
|
* 根据名称获取规则IDS
|
|||
|
* @param string $name
|
|||
|
* @return array
|
|||
|
*/
|
|||
|
public static function getAuthRuleIdsByName($name)
|
|||
|
{
|
|||
|
$ids = [];
|
|||
|
$menu = AuthRule::getByName($name);
|
|||
|
if ($menu) {
|
|||
|
// 必须将结果集转换为数组
|
|||
|
$ruleList = collection(AuthRule::order('weigh', 'desc')->field('id,pid,name')->select())->toArray();
|
|||
|
// 构造菜单数据
|
|||
|
$ids = Tree::instance()->init($ruleList)->getChildrenIds($menu['id'], true);
|
|||
|
}
|
|||
|
return $ids;
|
|||
|
}
|
|||
|
|
|||
|
}
|