Menu.php 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156
  1. <?php
  2. namespace app\common\library;
  3. use Throwable;
  4. use app\admin\model\AdminRule;
  5. use app\admin\model\UserRule;
  6. /**
  7. * 菜单规则管理类
  8. */
  9. class Menu
  10. {
  11. /**
  12. * @param array $menu
  13. * @param int|string $parent 父级规则name或id
  14. * @param string $mode 添加模式(规则重复时):cover=覆盖旧菜单,rename=重命名新菜单,ignore=忽略
  15. * @param string $position 位置:backend=后台,frontend=前台
  16. * @return void
  17. * @throws Throwable
  18. */
  19. public static function create(array $menu, int|string $parent = 0, string $mode = 'cover', string $position = 'backend'): void
  20. {
  21. $pid = 0;
  22. $model = $position == 'backend' ? new AdminRule() : new UserRule();
  23. $parentRule = $model->where((is_numeric($parent) ? 'id' : 'name'), $parent)->find();
  24. if ($parentRule) {
  25. $pid = $parentRule['id'];
  26. }
  27. foreach ($menu as $item) {
  28. if (!self::requiredAttrCheck($item)) {
  29. continue;
  30. }
  31. // 属性
  32. $item['status'] = 1;
  33. if (!isset($item['pid'])) {
  34. $item['pid'] = $pid;
  35. }
  36. $sameOldMenu = $model->where('name', $item['name'])->find();
  37. if ($sameOldMenu) {
  38. // 存在相同名称的菜单规则
  39. if ($mode == 'cover') {
  40. $sameOldMenu->save($item);
  41. } elseif ($mode == 'rename') {
  42. $count = $model->where('name', $item['name'])->count();
  43. $item['name'] = $item['name'] . '-CONFLICT-' . $count;
  44. $item['path'] = $item['path'] . '-CONFLICT-' . $count;
  45. $item['title'] = $item['title'] . '-CONFLICT-' . $count;
  46. $sameOldMenu = $model->create($item);
  47. } elseif ($mode == 'ignore') {
  48. // 忽略同名菜单时,当前 pid 下没有同名菜单,则创建同名新菜单,以保证所有新增菜单的上下级结构
  49. $sameOldMenu = $model
  50. ->where('name', $item['name'])
  51. ->where('pid', $item['pid'])
  52. ->find();
  53. if (!$sameOldMenu) {
  54. $sameOldMenu = $model->create($item);
  55. }
  56. }
  57. } else {
  58. $sameOldMenu = $model->create($item);
  59. }
  60. if (!empty($item['children'])) {
  61. self::create($item['children'], $sameOldMenu['id'], $mode, $position);
  62. }
  63. }
  64. }
  65. /**
  66. * 删菜单
  67. * @param string|int $id 规则name或id
  68. * @param bool $recursion 是否递归删除子级菜单、是否删除自身,是否删除上级空菜单
  69. * @param string $position 位置:backend=后台,frontend=前台
  70. * @return bool
  71. * @throws Throwable
  72. */
  73. public static function delete(string|int $id, bool $recursion = false, string $position = 'backend'): bool
  74. {
  75. if (!$id) {
  76. return true;
  77. }
  78. $model = $position == 'backend' ? new AdminRule() : new UserRule();
  79. $menuRule = $model->where((is_numeric($id) ? 'id' : 'name'), $id)->find();
  80. if (!$menuRule) {
  81. return true;
  82. }
  83. $children = $model->where('pid', $menuRule['id'])->select()->toArray();
  84. if ($recursion && $children) {
  85. foreach ($children as $child) {
  86. self::delete($child['id'], true, $position);
  87. }
  88. }
  89. if (!$children || $recursion) {
  90. $menuRule->delete();
  91. self::delete($menuRule->pid, false, $position);
  92. }
  93. return true;
  94. }
  95. /**
  96. * 启用菜单
  97. * @param string|int $id 规则name或id
  98. * @param string $position 位置:backend=后台,frontend=前台
  99. * @return bool
  100. * @throws Throwable
  101. */
  102. public static function enable(string|int $id, string $position = 'backend'): bool
  103. {
  104. $model = $position == 'backend' ? new AdminRule() : new UserRule();
  105. $menuRule = $model->where((is_numeric($id) ? 'id' : 'name'), $id)->find();
  106. if (!$menuRule) {
  107. return false;
  108. }
  109. $menuRule->status = 1;
  110. $menuRule->save();
  111. return true;
  112. }
  113. /**
  114. * 禁用菜单
  115. * @param string|int $id 规则name或id
  116. * @param string $position 位置:backend=后台,frontend=前台
  117. * @return bool
  118. * @throws Throwable
  119. */
  120. public static function disable(string|int $id, string $position = 'backend'): bool
  121. {
  122. $model = $position == 'backend' ? new AdminRule() : new UserRule();
  123. $menuRule = $model->where((is_numeric($id) ? 'id' : 'name'), $id)->find();
  124. if (!$menuRule) {
  125. return false;
  126. }
  127. $menuRule->status = 0;
  128. $menuRule->save();
  129. return true;
  130. }
  131. public static function requiredAttrCheck($menu): bool
  132. {
  133. $attrs = ['type', 'title', 'name'];
  134. foreach ($attrs as $attr) {
  135. if (!array_key_exists($attr, $menu)) {
  136. return false;
  137. }
  138. if (!$menu[$attr]) {
  139. return false;
  140. }
  141. }
  142. return true;
  143. }
  144. }