}> */ public static function portal(): array { return [ ['label' => null, 'items' => [ ['dashboard', 'gauge', 'overview', null], ['cloud', 'cloud', 'cloud', null], ['users', 'users', 'users', null], ['backups', 'database', 'backups', null], ]], ['label' => __('dashboard.nav_group.contract'), 'items' => [ ['billing', 'box', 'billing', null], ['invoices', 'receipt', 'invoices', null], ['settings', 'settings', 'settings', null], ['support', 'life-buoy', 'support', null], ]], ]; } /** @return array}> */ public static function console(): array { return [ ['label' => null, 'items' => [ ['admin.overview', 'gauge', 'overview', null], ['admin.customers', 'users', 'customers', null], ['admin.instances', 'box', 'instances', null], ['admin.hosts', 'server', 'hosts', null], ['admin.datacenters', 'database', 'datacenters', null], ['admin.plans', 'tag', 'plans', 'plans.manage'], ]], ['label' => __('admin.nav_group.operations'), 'items' => [ ['admin.provisioning', 'activity', 'provisioning', null], ['admin.maintenance', 'alert-triangle', 'maintenance', null], ['admin.vpn', 'shield', 'vpn', null], ['admin.revenue', 'trending-up', 'revenue', null], // Its own entry, not a section of Settings: what is set here // appears on a legal document, and burying it beside the // site-visibility switch invites somebody to change one in passing. ['admin.finance', 'receipt', 'finance', 'site.manage'], ]], ['label' => __('admin.nav_group.system'), 'items' => [ ['admin.mail', 'mail', 'mail', 'mail.manage'], ['admin.secrets', 'lock', 'secrets', 'secrets.manage'], ['admin.infrastructure', 'globe', 'infrastructure', 'hosts.manage'], ['admin.settings', 'settings', 'settings', null], // null capability, deliberately: the compulsory two-factor // switch (Admin\Settings::saveTwoFactorPolicy()) applies to // every operator, so enrolment has to be reachable by every // operator too, not only the ones who can manage the site. ['admin.two-factor-setup', 'shield-check', 'two_factor_setup', null], ]], ]; } /** * The label of the entry the current request belongs to. * * Matched on the route rather than the path, because the console's path * changes between host-bound and fallback mode while its route names do * not. Null when the page is not in the navigation at all — a detail view, * a modal — and the caller then supplies its own title. */ public static function currentLabel(bool $console = false): ?string { $prefix = $console ? 'admin.nav.' : 'dashboard.nav.'; foreach ($console ? self::console() : self::portal() as $group) { foreach ($group['items'] as [$route, , $key]) { $matches = $console ? AdminArea::routeIs($route) : request()->routeIs($route); if ($matches) { return __($prefix.$key); } } } return null; } }