148 lines
4.8 KiB
PHP
148 lines
4.8 KiB
PHP
<?php
|
||
|
||
namespace App\Utilities;
|
||
|
||
use App\Models\Auth\User;
|
||
|
||
class SidebarPermissions
|
||
{
|
||
public static function settings(): array
|
||
{
|
||
$value = setting('system.sidebar_permissions', []);
|
||
|
||
if (is_string($value)) {
|
||
$value = json_decode($value, true) ?: [];
|
||
}
|
||
|
||
return is_array($value) ? $value : [];
|
||
}
|
||
|
||
public static function subjectKey(User $user): string
|
||
{
|
||
$userKey = 'user_' . $user->id;
|
||
$settings = self::settings();
|
||
|
||
if (in_array($userKey, $settings['configured'] ?? [], true)) {
|
||
return $userKey;
|
||
}
|
||
|
||
return 'role_' . SystemAccess::roleName($user);
|
||
}
|
||
|
||
public static function allowedKeys(User $user): ?array
|
||
{
|
||
$settings = self::settings();
|
||
$subject = self::subjectKey($user);
|
||
|
||
if (! in_array($subject, $settings['configured'] ?? [], true)) {
|
||
return null;
|
||
}
|
||
|
||
return array_values(array_unique((array) ($settings['subjects'][$subject] ?? [])));
|
||
}
|
||
|
||
public static function navigationFor(User $user): array
|
||
{
|
||
$navigation = BusinessNavigation::all();
|
||
$allowed = self::allowedKeys($user);
|
||
|
||
if ($allowed === null) {
|
||
return $navigation;
|
||
}
|
||
|
||
$navigation = array_values(array_filter(array_map(function (array $section) use ($allowed) {
|
||
$sectionKey = $section['slug'];
|
||
|
||
if (in_array($sectionKey, $allowed, true)) {
|
||
return $section;
|
||
}
|
||
|
||
$pages = array_values(array_filter($section['pages'] ?? [], function (array $page) use ($allowed, $sectionKey) {
|
||
$pageKey = $sectionKey . '/' . $page['slug'];
|
||
|
||
if (in_array($pageKey, $allowed, true)) {
|
||
// 若有 children,保留 children 的精确权限过滤
|
||
if (! empty($page['children'])) {
|
||
$page['children'] = array_values(array_filter($page['children'], function (array $child) use ($allowed, $sectionKey) {
|
||
return in_array($sectionKey . '/' . $child['slug'], $allowed, true);
|
||
}));
|
||
}
|
||
return true;
|
||
}
|
||
|
||
// 子页面可能在 allowed 列表中(独立 URL),父级分组也允许展开
|
||
if (! empty($page['children'])) {
|
||
$visibleChildren = array_values(array_filter($page['children'], function (array $child) use ($allowed, $sectionKey) {
|
||
return in_array($sectionKey . '/' . $child['slug'], $allowed, true);
|
||
}));
|
||
if (! empty($visibleChildren)) {
|
||
$page['children'] = $visibleChildren;
|
||
return true;
|
||
}
|
||
}
|
||
|
||
return false;
|
||
}));
|
||
|
||
if (! empty($pages)) {
|
||
$section['pages'] = $pages;
|
||
|
||
return $section;
|
||
}
|
||
|
||
return null;
|
||
}, $navigation)));
|
||
|
||
// 新增的公司成本安排、税金预测表与主体经营报表共用公司经营报表权限。
|
||
// 对已经保存过精确权限的账号兼容旧配置,避免新增页面被旧权限集合隐藏。
|
||
foreach ($navigation as &$section) {
|
||
if (($section['slug'] ?? null) !== 'company-management') {
|
||
continue;
|
||
}
|
||
|
||
$hasSubjectReport = collect($section['pages'] ?? [])->contains('slug', 'subject-operating-report');
|
||
|
||
if ($hasSubjectReport) {
|
||
$configuredPages = collect(BusinessNavigation::all())
|
||
->firstWhere('slug', 'company-management')['pages'] ?? [];
|
||
|
||
foreach (['company-cost-arrangement', 'tax-forecast'] as $sharedReportSlug) {
|
||
$alreadyVisible = collect($section['pages'] ?? [])->contains('slug', $sharedReportSlug);
|
||
|
||
if ($alreadyVisible) {
|
||
continue;
|
||
}
|
||
|
||
$sharedReportPage = collect($configuredPages)->firstWhere('slug', $sharedReportSlug);
|
||
|
||
if ($sharedReportPage) {
|
||
$section['pages'][] = $sharedReportPage;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
unset($section);
|
||
|
||
return $navigation;
|
||
}
|
||
|
||
public static function allKeys(): array
|
||
{
|
||
$keys = [];
|
||
|
||
foreach (BusinessNavigation::all() as $section) {
|
||
$keys[] = $section['slug'];
|
||
|
||
foreach ($section['pages'] ?? [] as $page) {
|
||
$keys[] = $section['slug'] . '/' . $page['slug'];
|
||
|
||
foreach ($page['children'] ?? [] as $child) {
|
||
$keys[] = $section['slug'] . '/' . $child['slug'];
|
||
}
|
||
}
|
||
}
|
||
|
||
return $keys;
|
||
}
|
||
}
|