Merge pull request #60961 from nextcloud/backport/60458/stable34

[stable34] refactor(NavigationManager): move navigation definitions into apps
This commit is contained in:
Andy Scherzinger 2026-06-03 20:36:09 +02:00 committed by GitHub
commit 3c33f5e2e0
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
14 changed files with 248 additions and 324 deletions

View file

@ -19,4 +19,21 @@
<dependencies>
<nextcloud min-version="34" max-version="34"/>
</dependencies>
<navigations>
<navigation role="admin">
<name>Appstore</name>
<route>appstore.page.viewApps</route>
<icon>app.svg</icon>
<order>99</order>
</navigation>
<navigation role="admin">
<name>Apps</name>
<route>appstore.page.viewApps</route>
<icon>app.svg</icon>
<order>5</order>
<type>settings</type>
</navigation>
</navigations>
</info>

View file

@ -23,7 +23,6 @@ use OCP\AppFramework\Http\TemplateResponse;
use OCP\AppFramework\Services\IInitialState;
use OCP\IConfig;
use OCP\IL10N;
use OCP\INavigationManager;
use OCP\IRequest;
use OCP\IURLGenerator;
use OCP\Server;
@ -41,7 +40,6 @@ final class PageController extends Controller {
private readonly IURLGenerator $urlGenerator,
private readonly IInitialState $initialState,
private readonly BundleFetcher $bundleFetcher,
private readonly INavigationManager $navigationManager,
) {
parent::__construct(Application::APP_ID, $request);
}
@ -51,8 +49,6 @@ final class PageController extends Controller {
#[FrontpageRoute(verb: 'GET', url: '/settings/apps/{category}', defaults: ['category' => ''], root: '')]
#[FrontpageRoute(verb: 'GET', url: '/settings/apps/{category}/{id}', defaults: ['category' => '', 'id' => ''], root: '')]
public function viewApps(): TemplateResponse {
$this->navigationManager->setActiveEntry('core_apps');
$this->initialState->provideInitialState('appstoreEnabled', $this->config->getSystemValueBool('appstoreenabled', true));
$this->initialState->provideInitialState('appstoreBundles', $this->getBundles());
$this->initialState->provideInitialState('appstoreDeveloperDocs', $this->urlGenerator->linkToDocs('developer-manual'));

View file

@ -16,7 +16,6 @@ use OCP\AppFramework\Http\TemplateResponse;
use OCP\AppFramework\Services\IInitialState;
use OCP\IConfig;
use OCP\IL10N;
use OCP\INavigationManager;
use OCP\IRequest;
use OCP\IURLGenerator;
use PHPUnit\Framework\MockObject\MockObject;
@ -30,8 +29,6 @@ final class PageControllerTest extends TestCase {
private IConfig&MockObject $config;
private INavigationManager&MockObject $navigationManager;
private IAppManager&MockObject $appManager;
private BundleFetcher&MockObject $bundleFetcher;
@ -54,7 +51,6 @@ final class PageControllerTest extends TestCase {
->method('t')
->willReturnArgument(0);
$this->config = $this->createMock(IConfig::class);
$this->navigationManager = $this->createMock(INavigationManager::class);
$this->appManager = $this->createMock(IAppManager::class);
$this->bundleFetcher = $this->createMock(BundleFetcher::class);
$this->installer = $this->createMock(Installer::class);
@ -70,7 +66,6 @@ final class PageControllerTest extends TestCase {
$this->urlGenerator,
$this->initialState,
$this->bundleFetcher,
$this->navigationManager,
);
}
@ -84,10 +79,6 @@ final class PageControllerTest extends TestCase {
->method('getSystemValueBool')
->with('appstoreenabled', true)
->willReturn(true);
$this->navigationManager
->expects($this->once())
->method('setActiveEntry')
->with('core_apps');
$this->initialState
->expects($this->exactly(4))
@ -117,10 +108,6 @@ final class PageControllerTest extends TestCase {
->method('getSystemValueBool')
->with('appstoreenabled', true)
->willReturn(false);
$this->navigationManager
->expects($this->once())
->method('setActiveEntry')
->with('core_apps');
$this->initialState
->expects($this->exactly(4))

View file

@ -16,6 +16,11 @@ use OCP\AppFramework\Bootstrap\IBootstrap;
use OCP\AppFramework\Bootstrap\IRegistrationContext;
use OCP\Collaboration\Reference\RenderReferenceEvent;
use OCP\INavigationManager;
use OCP\IURLGenerator;
use OCP\IUserSession;
use OCP\L10N\IFactory;
use OCP\Server;
class Application extends App implements IBootstrap {
public const APP_ID = 'profile';
@ -32,5 +37,33 @@ class Application extends App implements IBootstrap {
#[\Override]
public function boot(IBootContext $context): void {
$context->injectFn($this->registerNavigationEntry(...));
}
/**
* Registers the navigation entry for the profile app in the user settings.
* Needed as the href is dynamic and thus we cannot use the appinfo/info.xml
*/
public function registerNavigationEntry(
INavigationManager $navigationManager,
IUserSession $userSession,
IURLGenerator $urlGenerator,
): void {
if (!$userSession->isLoggedIn()) {
return;
}
$l = Server::get(IFactory::class)->get('profile');
// Profile
$navigationManager->add([
'type' => 'settings',
'id' => 'profile',
'order' => 1,
'href' => $urlGenerator->linkToRoute(
'profile.ProfilePage.index',
['targetUserId' => $userSession->getUser()->getUID()],
),
'name' => $l->t('View profile'),
]);
}
}

View file

@ -74,6 +74,5 @@
<provider>OCA\Settings\Activity\Provider</provider>
<provider>OCA\Settings\Activity\SecurityProvider</provider>
</providers>
</activity>
</info>

View file

@ -33,7 +33,7 @@ return [
['name' => 'CheckSetup#getFailedIntegrityCheckFiles', 'url' => '/settings/integrity/failed', 'verb' => 'GET' , 'root' => ''],
['name' => 'CheckSetup#rescanFailedIntegrityCheck', 'url' => '/settings/integrity/rescan', 'verb' => 'GET' , 'root' => ''],
['name' => 'PersonalSettings#index', 'url' => '/settings/user/{section}', 'verb' => 'GET', 'defaults' => ['section' => 'personal-info'] , 'root' => ''],
['name' => 'AdminSettings#index', 'url' => '/settings/admin/{section}', 'verb' => 'GET', 'defaults' => ['section' => 'server'] , 'root' => ''],
['name' => 'AdminSettings#index', 'url' => '/settings/admin/{section}', 'verb' => 'GET', 'defaults' => ['section' => 'overview'] , 'root' => ''],
['name' => 'AdminSettings#form', 'url' => '/settings/admin/{section}', 'verb' => 'GET' , 'root' => ''],
['name' => 'ChangePassword#changePersonalPassword', 'url' => '/settings/personal/changepassword', 'verb' => 'POST' , 'root' => ''],
['name' => 'ChangePassword#changeUserPassword', 'url' => '/settings/users/changepassword', 'verb' => 'POST' , 'root' => ''],

View file

@ -90,8 +90,12 @@ use OCP\Defaults;
use OCP\Group\Events\GroupDeletedEvent;
use OCP\Group\Events\UserAddedEvent;
use OCP\Group\Events\UserRemovedEvent;
use OCP\Group\ISubAdmin;
use OCP\IConfig;
use OCP\IGroupManager;
use OCP\INavigationManager;
use OCP\IURLGenerator;
use OCP\IUserSession;
use OCP\L10N\IFactory;
use OCP\Mail\IMailer;
use OCP\Security\ICrypto;
@ -226,5 +230,93 @@ class Application extends App implements IBootstrap {
#[\Override]
public function boot(IBootContext $context): void {
$context->injectFn($this->registerNavigationEntries(...));
}
/**
* Registers the navigation entries for the user settings.
* Needed as some entries are dynamic and thus we cannot use the appinfo/info.xml
*
* Registers the following entries:
* - Appearance and accessibility
* - Personal settings (named "Settings" for non-admins)
* - Accounts (only for subadmins)
* - Help & privacy (conditionally enabled based on config)
*/
public function registerNavigationEntries(
INavigationManager $navigationManager,
IURLGenerator $urlGenerator,
IUserSession $userSession,
IConfig $config,
): void {
if ($userSession->getUser() === null) {
return;
}
$l = Server::get(IFactory::class)
->get('settings');
$groupManager = Server::get(IGroupManager::class);
$subAdmin = Server::get(ISubAdmin::class);
$isAdmin = $groupManager->isAdmin($userSession->getUser()->getUID());
$isSubAdmin = $subAdmin->isSubAdmin($userSession->getUser());
// Accessibility settings - the URL is dynamic (route parameters) which is currently not supported by appinfo.xml
$navigationManager->add([
'type' => 'settings',
'id' => 'accessibility_settings',
'order' => 2,
'href' => $urlGenerator->linkToRoute('settings.PersonalSettings.index', ['section' => 'theming']),
'name' => $l->t('Appearance and accessibility'),
'icon' => $urlGenerator->imagePath('theming', 'accessibility-dark.svg'),
]);
// Personal settings - this entry is dynamic so we cannot use appinfo
$navigationManager->add([
'type' => 'settings',
'id' => 'settings_personal',
'order' => 3,
'href' => $urlGenerator->linkToRoute('settings.PersonalSettings.index'),
'name' => $isAdmin
? $l->t('Personal settings')
: $l->t('Settings'),
'icon' => $isAdmin
? $urlGenerator->imagePath('settings', 'personal.svg')
: $urlGenerator->imagePath('settings', 'admin.svg'),
]);
if ($isAdmin) {
$navigationManager->add([
'type' => 'settings',
'id' => 'settings_administration',
'order' => 4,
'href' => $urlGenerator->linkToRoute('settings.adminSettings.index'),
'name' => $l->t('Administration settings'),
'icon' => $urlGenerator->imagePath('settings', 'admin.svg'),
]);
}
// User management is conditionally enabled for subadmins, but appinfo currently only supports full admins
if ($isSubAdmin) {
$navigationManager->add([
'type' => 'settings',
'id' => 'core_users',
'order' => 6,
'href' => $urlGenerator->linkToRoute('settings.Users.usersList'),
'name' => $l->t('Accounts'),
'icon' => $urlGenerator->imagePath('settings', 'users.svg'),
]);
}
// conditionally enabled navigation entry
if ($config->getSystemValueBool('knowledgebaseenabled', true)) {
$navigationManager->add([
'type' => 'settings',
'id' => 'help',
'order' => 99998,
'href' => $urlGenerator->linkToRoute('settings.Help.help'),
'name' => $l->t('Help & privacy'),
'icon' => $urlGenerator->imagePath('settings', 'help.svg'),
]);
}
}
}

View file

@ -32,6 +32,11 @@ use OCP\AppFramework\Http\Events\BeforeLoginTemplateRenderedEvent;
use OCP\AppFramework\Http\Events\BeforeTemplateRenderedEvent;
use OCP\DB\Events\AddMissingIndicesEvent;
use OCP\DB\Events\AddMissingPrimaryKeyEvent;
use OCP\INavigationManager;
use OCP\IURLGenerator;
use OCP\IUserSession;
use OCP\L10N\IFactory;
use OCP\Server;
use OCP\User\Events\BeforeUserDeletedEvent;
use OCP\User\Events\PasswordUpdatedEvent;
use OCP\User\Events\UserDeletedEvent;
@ -93,7 +98,36 @@ class Application extends App implements IBootstrap {
#[\Override]
public function boot(IBootContext $context): void {
// ...
$context->injectFn($this->registerNavigationEntries(...));
}
/**
* Registers the navigation entries for the core app:
* - The logout button in the settings menu
*/
public function registerNavigationEntries(
INavigationManager $navigationManager,
IUserSession $userSession,
IURLGenerator $urlGenerator,
): void {
if (!$userSession->isLoggedIn()) {
return;
}
$l = Server::get(IFactory::class)->get('core');
// Register the logout button in the user settings
$logoutUrl = \OC_User::getLogoutUrl($urlGenerator);
if ($logoutUrl !== '') {
$navigationManager->add([
'type' => 'settings',
'id' => 'logout',
'order' => 99999,
'href' => $logoutUrl,
'name' => $l->t('Log out'),
'icon' => $urlGenerator->imagePath('core', 'actions/logout.svg'),
]);
}
}
}

View file

@ -21,7 +21,7 @@ describe('Create system tags', () => {
// login as admin and go to admin settings
cy.login(admin)
cy.visit('/settings/admin')
cy.visit('/settings/admin/server')
})
it('Can create a tag', () => {
@ -48,7 +48,7 @@ describe('Create system tags', () => {
describe('Update system tags', { testIsolation: false }, () => {
before(() => {
cy.login(admin)
cy.visit('/settings/admin')
cy.visit('/settings/admin/server')
})
it('select the tag', () => {
@ -92,7 +92,7 @@ describe('Update system tags', { testIsolation: false }, () => {
describe('Delete system tags', { testIsolation: false }, () => {
before(() => {
cy.login(admin)
cy.visit('/settings/admin')
cy.visit('/settings/admin/server')
})
it('select the tag', () => {

View file

@ -154,7 +154,7 @@ describe('Admin theming: Change the login fields then reset them', function() {
it('See the admin theming section', function() {
cy.visit('/settings/admin/theming')
cy.findByRole('heading', { name: /^Theming/ })
cy.findByRole('heading', { name: /^Theming/, level: 2 })
.should('exist')
.scrollIntoView()
})

View file

@ -850,6 +850,7 @@ class OC {
// Make sure that the application class is not loaded before the database is setup
if ($systemConfig->getValue('installed', false)) {
$appManager->loadApp('core');
$appManager->loadApp('settings');
}

View file

@ -1187,8 +1187,11 @@ class AppManager implements IAppManager {
#[\Override]
public function getAppNamespace(string $appId): string {
$topNamespace = 'OCA\\';
if ($appId === 'core') {
return 'OC\\Core';
}
$topNamespace = 'OCA\\';
// Hit the cache!
if (isset($this->namespaceCache[$appId])) {
return $topNamespace . $this->namespaceCache[$appId];

View file

@ -8,7 +8,6 @@
namespace OC;
use InvalidArgumentException;
use OC\Group\Manager;
use OCP\App\IAppManager;
use OCP\EventDispatcher\IEventDispatcher;
use OCP\IConfig;
@ -203,109 +202,6 @@ class NavigationManager implements INavigationManager {
$this->init = true;
$l = $this->l10nFac->get('lib');
if ($this->config->getSystemValueBool('knowledgebaseenabled', true)) {
$this->add([
'type' => 'settings',
'id' => 'help',
'order' => 99998,
'href' => $this->urlGenerator->linkToRoute('settings.Help.help'),
'name' => $l->t('Help & privacy'),
'icon' => $this->urlGenerator->imagePath('settings', 'help.svg'),
]);
}
if ($this->userSession->isLoggedIn()) {
// Profile
$this->add([
'type' => 'settings',
'id' => 'profile',
'order' => 1,
'href' => $this->urlGenerator->linkToRoute(
'profile.ProfilePage.index',
['targetUserId' => $this->userSession->getUser()->getUID()],
),
'name' => $l->t('View profile'),
]);
// Accessibility settings
if ($this->appManager->isEnabledForUser('theming', $this->userSession->getUser())) {
$this->add([
'type' => 'settings',
'id' => 'accessibility_settings',
'order' => 2,
'href' => $this->urlGenerator->linkToRoute('settings.PersonalSettings.index', ['section' => 'theming']),
'name' => $l->t('Appearance and accessibility'),
'icon' => $this->urlGenerator->imagePath('theming', 'accessibility-dark.svg'),
]);
}
if ($this->isAdmin()) {
// App management
$this->add([
'type' => 'settings',
'id' => 'core_apps',
'order' => 5,
'href' => $this->urlGenerator->linkToRoute('appstore.Page.viewApps'),
'icon' => $this->urlGenerator->imagePath('appstore', 'app.svg'),
'name' => $l->t('Apps'),
]);
// Personal settings
$this->add([
'type' => 'settings',
'id' => 'settings',
'order' => 3,
'href' => $this->urlGenerator->linkToRoute('settings.PersonalSettings.index'),
'name' => $l->t('Personal settings'),
'icon' => $this->urlGenerator->imagePath('settings', 'personal.svg'),
]);
// Admin settings
$this->add([
'type' => 'settings',
'id' => 'admin_settings',
'order' => 4,
'href' => $this->urlGenerator->linkToRoute('settings.AdminSettings.index', ['section' => 'overview']),
'name' => $l->t('Administration settings'),
'icon' => $this->urlGenerator->imagePath('settings', 'admin.svg'),
]);
} else {
// Personal settings
$this->add([
'type' => 'settings',
'id' => 'settings',
'order' => 3,
'href' => $this->urlGenerator->linkToRoute('settings.PersonalSettings.index'),
'name' => $l->t('Settings'),
'icon' => $this->urlGenerator->imagePath('settings', 'admin.svg'),
]);
}
$logoutUrl = \OC_User::getLogoutUrl($this->urlGenerator);
if ($logoutUrl !== '') {
// Logout
$this->add([
'type' => 'settings',
'id' => 'logout',
'order' => 99999,
'href' => $logoutUrl,
'name' => $l->t('Log out'),
'icon' => $this->urlGenerator->imagePath('core', 'actions/logout.svg'),
]);
}
if ($this->isSubadmin()) {
// User management
$this->add([
'type' => 'settings',
'id' => 'core_users',
'order' => 6,
'href' => $this->urlGenerator->linkToRoute('settings.Users.usersList'),
'name' => $l->t('Accounts'),
'icon' => $this->urlGenerator->imagePath('settings', 'users.svg'),
]);
}
}
$this->eventDispatcher->dispatchTyped(new LoadAdditionalEntriesEvent());
if ($this->userSession->isLoggedIn()) {
@ -316,10 +212,6 @@ class NavigationManager implements INavigationManager {
}
foreach ($apps as $app) {
if (!$this->userSession->isLoggedIn() && !$this->appManager->isEnabledForUser($app, $this->userSession->getUser())) {
continue;
}
// load plugins and collections from info.xml
$info = $this->appManager->getAppInfo($app);
if (!isset($info['navigations']['navigation'])) {
@ -365,14 +257,14 @@ class NavigationManager implements INavigationManager {
'order' => $order,
// Target of the navigation entry
'href' => $route,
// The icon used for the naviation entry
// The icon used for the navigation entry
'icon' => $icon,
// Type of the navigation entry ('link' vs 'settings')
'type' => $type,
// Localized name of the navigation entry
'name' => $l->t($nav['name']),
], $type === 'link' ? [
// App that registered this navigation entry (not necessarly the same as the id)
// App that registered this navigation entry (not necessarily the same as the id)
'app' => $app,
] : []
));
@ -388,14 +280,6 @@ class NavigationManager implements INavigationManager {
return false;
}
private function isSubadmin(): bool {
$user = $this->userSession->getUser();
if ($user !== null && $this->groupManager instanceof Manager) {
return $this->groupManager->getSubAdmin()->isSubAdmin($user);
}
return false;
}
#[Override]
public function setUnreadCounter(string $id, int $unreadCounter): void {
$this->unreadCounters[$id] = $unreadCounter;

View file

@ -11,8 +11,6 @@ namespace Test;
use OC\App\AppManager;
use OC\Group\Manager;
use OC\NavigationManager;
use OC\Security\CSRF\CsrfTokenManager;
use OC\SubAdmin;
use OCP\EventDispatcher\IEventDispatcher;
use OCP\IConfig;
use OCP\IGroupManager;
@ -22,7 +20,6 @@ use OCP\IUser;
use OCP\IUserSession;
use OCP\L10N\IFactory;
use OCP\Navigation\Events\LoadAdditionalEntriesEvent;
use OCP\Server;
use PHPUnit\Framework\MockObject\MockObject;
use Psr\Log\LoggerInterface;
@ -260,9 +257,6 @@ class NavigationManagerTest extends TestCase {
->with($user)
->willReturn(['test']);
$this->groupManager->expects($this->any())->method('isAdmin')->willReturn($isAdmin);
$subadmin = $this->createMock(SubAdmin::class);
$subadmin->expects($this->any())->method('isSubAdmin')->with($user)->willReturn(false);
$this->groupManager->expects($this->any())->method('getSubAdmin')->willReturn($subadmin);
$this->navigationManager->clear();
$this->dispatcher->expects($this->once())
@ -275,112 +269,21 @@ class NavigationManagerTest extends TestCase {
}
public static function providesNavigationConfig(): array {
$apps = [
'core_apps' => [
'id' => 'core_apps',
'order' => 5,
'href' => '/apps/test/',
'icon' => '/apps/appstore/img/app.svg',
'name' => 'Apps',
'active' => false,
'type' => 'settings',
'classes' => '',
'unread' => 0
]
];
$defaults = [
'profile' => [
'type' => 'settings',
'id' => 'profile',
'order' => 1,
'href' => '/apps/test/',
'name' => 'View profile',
'icon' => '',
'active' => false,
'classes' => '',
'unread' => 0,
],
'accessibility_settings' => [
'type' => 'settings',
'id' => 'accessibility_settings',
'order' => 2,
'href' => '/apps/test/',
'name' => 'Appearance and accessibility',
'icon' => '/apps/theming/img/accessibility-dark.svg',
'active' => false,
'classes' => '',
'unread' => 0,
],
'settings' => [
'id' => 'settings',
'order' => 3,
'href' => '/apps/test/',
'icon' => '/apps/settings/img/admin.svg',
'name' => 'Settings',
'active' => false,
'type' => 'settings',
'classes' => '',
'unread' => 0
],
'logout' => [
'id' => 'logout',
'order' => 99999,
'href' => 'https://example.com/logout?requesttoken=' . urlencode(Server::get(CsrfTokenManager::class)->getToken()->getEncryptedValue()),
'icon' => '/apps/core/img/actions/logout.svg',
'name' => 'Log out',
'active' => false,
'type' => 'settings',
'classes' => '',
'unread' => 0
]
];
$adminSettings = [
'accessibility_settings' => $defaults['accessibility_settings'],
'settings' => [
'id' => 'settings',
'order' => 3,
'href' => '/apps/test/',
'icon' => '/apps/settings/img/personal.svg',
'name' => 'Personal settings',
'active' => false,
'type' => 'settings',
'classes' => '',
'unread' => 0
],
'admin_settings' => [
'id' => 'admin_settings',
'order' => 4,
'href' => '/apps/test/',
'icon' => '/apps/settings/img/admin.svg',
'name' => 'Administration settings',
'active' => false,
'type' => 'settings',
'classes' => '',
'unread' => 0
]
];
return [
'minimalistic' => [
array_merge(
['profile' => $defaults['profile']],
['accessibility_settings' => $defaults['accessibility_settings']],
['settings' => $defaults['settings']],
['test' => [
'id' => 'test',
'order' => 100,
'href' => '/apps/test/',
'icon' => '/apps/test/img/app.svg',
'name' => 'Test',
'active' => false,
'type' => 'link',
'classes' => '',
'unread' => 0,
'default' => true,
'app' => 'test',
]],
['logout' => $defaults['logout']]
),
['test' => [
'id' => 'test',
'order' => 100,
'href' => '/apps/test/',
'icon' => '/apps/test/img/app.svg',
'name' => 'Test',
'active' => false,
'type' => 'link',
'classes' => '',
'unread' => 0,
'default' => true,
'app' => 'test',
]],
['navigations' => [
'navigation' => [
['route' => 'test.page.index', 'name' => 'Test']
@ -388,23 +291,17 @@ class NavigationManagerTest extends TestCase {
]]
],
'minimalistic-settings' => [
array_merge(
['profile' => $defaults['profile']],
['accessibility_settings' => $defaults['accessibility_settings']],
['settings' => $defaults['settings']],
['test' => [
'id' => 'test',
'order' => 100,
'href' => '/apps/test/',
'icon' => '/apps/test/img/app.svg',
'name' => 'Test',
'active' => false,
'type' => 'settings',
'classes' => '',
'unread' => 0,
]],
['logout' => $defaults['logout']]
),
['test' => [
'id' => 'test',
'order' => 100,
'href' => '/apps/test/',
'icon' => '/apps/test/img/app.svg',
'name' => 'Test',
'active' => false,
'type' => 'settings',
'classes' => '',
'unread' => 0,
]],
['navigations' => [
'navigation' => [
['route' => 'test.page.index', 'name' => 'Test', 'type' => 'settings']
@ -412,38 +309,32 @@ class NavigationManagerTest extends TestCase {
]]
],
'with-multiple' => [
array_merge(
['profile' => $defaults['profile']],
['accessibility_settings' => $defaults['accessibility_settings']],
['settings' => $defaults['settings']],
['test' => [
'id' => 'test',
'order' => 100,
['test' => [
'id' => 'test',
'order' => 100,
'href' => '/apps/test/',
'icon' => '/apps/test/img/app.svg',
'name' => 'Test',
'active' => false,
'type' => 'link',
'classes' => '',
'unread' => 0,
'default' => false,
'app' => 'test',
],
'test1' => [
'id' => 'test1',
'order' => 50,
'href' => '/apps/test/',
'icon' => '/apps/test/img/app.svg',
'name' => 'Test',
'name' => 'Other test',
'active' => false,
'type' => 'link',
'classes' => '',
'unread' => 0,
'default' => false,
'default' => true, // because of order
'app' => 'test',
],
'test1' => [
'id' => 'test1',
'order' => 50,
'href' => '/apps/test/',
'icon' => '/apps/test/img/app.svg',
'name' => 'Other test',
'active' => false,
'type' => 'link',
'classes' => '',
'unread' => 0,
'default' => true, // because of order
'app' => 'test',
]],
['logout' => $defaults['logout']]
),
]],
['navigations' => [
'navigation' => [
['route' => 'test.page.index', 'name' => 'Test'],
@ -452,25 +343,19 @@ class NavigationManagerTest extends TestCase {
]]
],
'admin' => [
array_merge(
['profile' => $defaults['profile']],
$adminSettings,
$apps,
['test' => [
'id' => 'test',
'order' => 100,
'href' => '/apps/test/',
'icon' => '/apps/test/img/app.svg',
'name' => 'Test',
'active' => false,
'type' => 'link',
'classes' => '',
'unread' => 0,
'default' => true,
'app' => 'test',
]],
['logout' => $defaults['logout']]
),
['test' => [
'id' => 'test',
'order' => 100,
'href' => '/apps/test/',
'icon' => '/apps/test/img/app.svg',
'name' => 'Test',
'active' => false,
'type' => 'link',
'classes' => '',
'unread' => 0,
'default' => true,
'app' => 'test',
]],
['navigations' => [
'navigation' => [
['@attributes' => ['role' => 'admin'], 'route' => 'test.page.index', 'name' => 'Test']
@ -479,12 +364,7 @@ class NavigationManagerTest extends TestCase {
true
],
'no name' => [
array_merge(
['profile' => $defaults['profile']],
$adminSettings,
$apps,
['logout' => $defaults['logout']]
),
[], // nothing because the entry is not added because it has no name
['navigations' => [
'navigation' => [
['@attributes' => ['role' => 'admin'], 'route' => 'test.page.index']
@ -493,12 +373,13 @@ class NavigationManagerTest extends TestCase {
true
],
'no admin' => [
$defaults,
[], // nothing because user is not an admin
['navigations' => [
'navigation' => [
['@attributes' => ['role' => 'admin'], 'route' => 'test.page.index', 'name' => 'Test']
],
]],
false,
]
];
}
@ -567,9 +448,6 @@ class NavigationManagerTest extends TestCase {
->with($user)
->willReturn(['test']);
$this->groupManager->expects($this->any())->method('isAdmin')->willReturn(false);
$subadmin = $this->createMock(SubAdmin::class);
$subadmin->expects($this->any())->method('isSubAdmin')->with($user)->willReturn(false);
$this->groupManager->expects($this->any())->method('getSubAdmin')->willReturn($subadmin);
$this->navigationManager->clear();
$this->dispatcher->expects($this->once())