Skip to content

Commit

Permalink
fix(NavigationManager): Skip invalid default navigation entries
Browse files Browse the repository at this point in the history
Signed-off-by: provokateurin <kate@provokateurin.de>
  • Loading branch information
provokateurin committed Sep 9, 2024
1 parent 0a3093d commit d5e98cd
Show file tree
Hide file tree
Showing 4 changed files with 90 additions and 14 deletions.
4 changes: 3 additions & 1 deletion apps/theming/lib/Settings/Admin.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
use OCP\AppFramework\Services\IInitialState;
use OCP\IConfig;
use OCP\IL10N;
use OCP\INavigationManager;
use OCP\IURLGenerator;
use OCP\Settings\IDelegatedSettings;
use OCP\Util;
Expand All @@ -28,6 +29,7 @@ public function __construct(
private IInitialState $initialState,
private IURLGenerator $urlGenerator,
private ImageManager $imageManager,
private INavigationManager $navigationManager,
) {
}

Expand Down Expand Up @@ -70,7 +72,7 @@ public function getForm(): TemplateResponse {
'docUrlIcons' => $this->urlGenerator->linkToDocs('admin-theming-icons'),
'canThemeIcons' => $this->imageManager->shouldReplaceIcons(),
'userThemingDisabled' => $this->themingDefaults->isUserThemingDisabled(),
'defaultApps' => array_filter(explode(',', $this->config->getSystemValueString('defaultapp', ''))),
'defaultApps' => $this->navigationManager->getDefaultEntryIds(),
]);

Util::addScript($this->appName, 'admin-theming');
Expand Down
6 changes: 5 additions & 1 deletion apps/theming/tests/Settings/AdminTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
use OCP\AppFramework\Services\IInitialState;
use OCP\IConfig;
use OCP\IL10N;
use OCP\INavigationManager;
use OCP\IURLGenerator;
use Test\TestCase;

Expand All @@ -24,6 +25,7 @@ class AdminTest extends TestCase {
private IURLGenerator $urlGenerator;
private ImageManager $imageManager;
private IL10N $l10n;
private INavigationManager $navigationManager;

protected function setUp(): void {
parent::setUp();
Expand All @@ -33,6 +35,7 @@ protected function setUp(): void {
$this->initialState = $this->createMock(IInitialState::class);
$this->urlGenerator = $this->createMock(IURLGenerator::class);
$this->imageManager = $this->createMock(ImageManager::class);
$this->navigationManager = $this->createMock(INavigationManager::class);

$this->admin = new Admin(
Application::APP_ID,
Expand All @@ -41,7 +44,8 @@ protected function setUp(): void {
$this->themingDefaults,
$this->initialState,
$this->urlGenerator,
$this->imageManager
$this->imageManager,
$this->navigationManager,
);
}

Expand Down
37 changes: 25 additions & 12 deletions lib/private/NavigationManager.php
Original file line number Diff line number Diff line change
Expand Up @@ -44,8 +44,6 @@ class NavigationManager implements INavigationManager {
private $groupManager;
/** @var IConfig */
private $config;
/** The default entry for the current user (cached for the `add` function) */
private ?string $defaultEntry;
/** User defined app order (cached for the `add` function) */
private array $customAppOrder;
private LoggerInterface $logger;
Expand All @@ -66,8 +64,6 @@ public function __construct(
$this->groupManager = $groupManager;
$this->config = $config;
$this->logger = $logger;

$this->defaultEntry = null;
}

/**
Expand Down Expand Up @@ -100,13 +96,22 @@ public function add($entry) {
$entry['app'] = $id;
}

// This is the default app that will always be shown first
$entry['default'] = ($entry['id'] ?? false) === $this->defaultEntry;
// Set order from user defined app order
$entry['order'] = (int)($this->customAppOrder[$id]['order'] ?? $entry['order'] ?? 100);
}

$this->entries[$id] = $entry;

// Needs to be done after adding the new entry to account for the default entries containing this new entry.
$this->updateDefaultEntries();
}

private function updateDefaultEntries() {
foreach ($this->entries as $id => $entry) {
if ($entry['type'] === 'link') {
$this->entries[$id]['default'] = $id === $this->getDefaultEntryIdForUser($this->userSession->getUser(), false);
}
}
}

/**
Expand Down Expand Up @@ -221,8 +226,6 @@ private function init() {
]);
}

$this->defaultEntry = $this->getDefaultEntryIdForUser($this->userSession->getUser(), false);

if ($this->userSession->isLoggedIn()) {
// Profile
$this->add([
Expand Down Expand Up @@ -422,8 +425,8 @@ public function get(string $id): array|null {

public function getDefaultEntryIdForUser(?IUser $user = null, bool $withFallbacks = true): string {
$this->init();
$defaultEntryIds = explode(',', $this->config->getSystemValueString('defaultapp', ''));
$defaultEntryIds = array_filter($defaultEntryIds);
// Disable fallbacks here, as we need to override them with the user defaults if none are configured.
$defaultEntryIds = $this->getDefaultEntryIds(false);

$user ??= $this->userSession->getUser();

Expand Down Expand Up @@ -461,8 +464,18 @@ public function getDefaultEntryIdForUser(?IUser $user = null, bool $withFallback
return $withFallbacks ? 'files' : '';
}

public function getDefaultEntryIds(): array {
return explode(',', $this->config->getSystemValueString('defaultapp', 'dashboard,files'));
public function getDefaultEntryIds(bool $withFallbacks = true): array {
$this->init();
$storedIds = explode(',', $this->config->getSystemValueString('defaultapp', $withFallbacks ? 'dashboard,files' : ''));
$ids = [];
$entryIds = array_keys($this->entries);
foreach ($storedIds as $id) {
if (in_array($id, $entryIds, true)) {
$ids[] = $id;
break;
}
}
return array_filter($ids);
}

public function setDefaultEntryIds(array $ids): void {
Expand Down
57 changes: 57 additions & 0 deletions tests/lib/NavigationManagerTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -724,4 +724,61 @@ public function testGetDefaultEntryIdForUser($defaultApps, $userDefaultApps, $us

$this->assertEquals($expectedApp, $this->navigationManager->getDefaultEntryIdForUser(null, $withFallbacks));
}

public function testDefaultEntryUpdated() {
$this->appManager->method('getInstalledApps')->willReturn([]);

$user = $this->createMock(IUser::class);
$user->method('getUID')->willReturn('user1');

$this->userSession
->method('getUser')
->willReturn($user);

$this->config
->method('getSystemValueString')
->with('defaultapp', $this->anything())
->willReturn('app4,app3,app2,app1');

$this->config
->method('getUserValue')
->willReturnMap([
['user1', 'core', 'defaultapp', '', ''],
['user1', 'core', 'apporder', '[]', ''],
]);

$this->navigationManager->add([
'id' => 'app1',
]);

$this->assertEquals('app1', $this->navigationManager->getDefaultEntryIdForUser(null, false));
$this->assertEquals(true, $this->navigationManager->get('app1')['default']);

$this->navigationManager->add([
'id' => 'app3',
]);

$this->assertEquals('app3', $this->navigationManager->getDefaultEntryIdForUser(null, false));
$this->assertEquals(false, $this->navigationManager->get('app1')['default']);
$this->assertEquals(true, $this->navigationManager->get('app3')['default']);

$this->navigationManager->add([
'id' => 'app2',
]);

$this->assertEquals('app3', $this->navigationManager->getDefaultEntryIdForUser(null, false));
$this->assertEquals(false, $this->navigationManager->get('app1')['default']);
$this->assertEquals(false, $this->navigationManager->get('app2')['default']);
$this->assertEquals(true, $this->navigationManager->get('app3')['default']);

$this->navigationManager->add([
'id' => 'app4',
]);

$this->assertEquals('app4', $this->navigationManager->getDefaultEntryIdForUser(null, false));
$this->assertEquals(false, $this->navigationManager->get('app1')['default']);
$this->assertEquals(false, $this->navigationManager->get('app2')['default']);
$this->assertEquals(false, $this->navigationManager->get('app3')['default']);
$this->assertEquals(true, $this->navigationManager->get('app4')['default']);
}
}

0 comments on commit d5e98cd

Please sign in to comment.