Skip to content

Commit c4eae96

Browse files
committed
feat(settings): conditionally display developer documentation link based on configuration
Signed-off-by: Arsalan Ul Haq Sohni <[email protected]>
1 parent e456794 commit c4eae96

File tree

3 files changed

+107
-1
lines changed

3 files changed

+107
-1
lines changed

apps/settings/lib/Controller/AppSettingsController.php

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@
3636
use OCP\Files\SimpleFS\ISimpleFile;
3737
use OCP\Files\SimpleFS\ISimpleFolder;
3838
use OCP\Http\Client\IClientService;
39+
use OCP\IAppConfig;
3940
use OCP\IConfig;
4041
use OCP\IGroup;
4142
use OCP\IGroupManager;
@@ -76,6 +77,7 @@ public function __construct(
7677
private IInitialState $initialState,
7778
private AppDiscoverFetcher $discoverFetcher,
7879
private IClientService $clientService,
80+
private IAppConfig $appConfig,
7981
) {
8082
parent::__construct($appName, $request);
8183
$this->appData = $appDataFactory->get('appstore');
@@ -92,7 +94,12 @@ public function viewApps(): TemplateResponse {
9294

9395
$this->initialState->provideInitialState('appstoreEnabled', $this->config->getSystemValueBool('appstoreenabled', true));
9496
$this->initialState->provideInitialState('appstoreBundles', $this->getBundles());
95-
$this->initialState->provideInitialState('appstoreDeveloperDocs', $this->urlGenerator->linkToDocs('developer-manual'));
97+
98+
// Conditionally set developer docs link based on configuration
99+
$displayDocumentationLink = $this->appConfig->getValueBool('settings', 'display_documentation_link', true);
100+
$developerDocsUrl = $displayDocumentationLink ? $this->urlGenerator->linkToDocs('developer-manual') : '';
101+
$this->initialState->provideInitialState('appstoreDeveloperDocs', $developerDocsUrl);
102+
96103
$this->initialState->provideInitialState('appstoreUpdateCount', count($this->getAppsWithUpdates()));
97104

98105
if ($this->appManager->isEnabledForAnyone('app_api')) {

apps/settings/src/views/AppStoreNavigation.vue

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,7 @@
101101
</template>
102102

103103
<NcAppNavigationItem
104+
v-if="developerDocsUrl"
104105
id="app-developer-docs"
105106
:name="t('settings', 'Developer documentation ↗')"
106107
:href="developerDocsUrl" />

apps/settings/tests/Controller/AppSettingsControllerTest.php

Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
use OCP\AppFramework\Services\IInitialState;
2121
use OCP\Files\AppData\IAppDataFactory;
2222
use OCP\Http\Client\IClientService;
23+
use OCP\IAppConfig;
2324
use OCP\IConfig;
2425
use OCP\IL10N;
2526
use OCP\INavigationManager;
@@ -40,6 +41,7 @@ class AppSettingsControllerTest extends TestCase {
4041
private IRequest&MockObject $request;
4142
private IL10N&MockObject $l10n;
4243
private IConfig&MockObject $config;
44+
private IAppConfig&MockObject $appConfig;
4345
private INavigationManager&MockObject $navigationManager;
4446
private AppManager&MockObject $appManager;
4547
private CategoryFetcher&MockObject $categoryFetcher;
@@ -65,6 +67,7 @@ protected function setUp(): void {
6567
->method('t')
6668
->willReturnArgument(0);
6769
$this->config = $this->createMock(IConfig::class);
70+
$this->appConfig = $this->createMock(IAppConfig::class);
6871
$this->navigationManager = $this->createMock(INavigationManager::class);
6972
$this->appManager = $this->createMock(AppManager::class);
7073
$this->categoryFetcher = $this->createMock(CategoryFetcher::class);
@@ -96,6 +99,7 @@ protected function setUp(): void {
9699
$this->initialState,
97100
$this->discoverFetcher,
98101
$this->clientService,
102+
$this->appConfig,
99103
);
100104
}
101105

@@ -164,6 +168,11 @@ public function testViewApps(): void {
164168
->method('getSystemValueBool')
165169
->with('appstoreenabled', true)
166170
->willReturn(true);
171+
$this->appConfig
172+
->expects($this->once())
173+
->method('getValueBool')
174+
->with('settings', 'display_documentation_link', true)
175+
->willReturn(true);
167176
$this->navigationManager
168177
->expects($this->once())
169178
->method('setActiveEntry')
@@ -209,6 +218,11 @@ public function testViewAppsAppstoreNotEnabled(): void {
209218
->method('getSystemValueBool')
210219
->with('appstoreenabled', true)
211220
->willReturn(false);
221+
$this->appConfig
222+
->expects($this->once())
223+
->method('getValueBool')
224+
->with('settings', 'display_documentation_link', true)
225+
->willReturn(true);
212226
$this->navigationManager
213227
->expects($this->once())
214228
->method('setActiveEntry')
@@ -243,4 +257,88 @@ public function testViewAppsAppstoreNotEnabled(): void {
243257

244258
$this->assertEquals($expected, $this->appSettingsController->viewApps());
245259
}
260+
261+
public function testDeveloperDocumentationLinkHiddenWhenConfigured(): void {
262+
$this->installer->expects($this->any())
263+
->method('isUpdateAvailable')
264+
->willReturn(false);
265+
$this->bundleFetcher->expects($this->once())->method('getBundles')->willReturn([]);
266+
$this->config
267+
->expects($this->once())
268+
->method('getSystemValueBool')
269+
->with('appstoreenabled', true)
270+
->willReturn(true);
271+
$this->appConfig
272+
->expects($this->once())
273+
->method('getValueBool')
274+
->with('settings', 'display_documentation_link', true)
275+
->willReturn(false);
276+
$this->navigationManager
277+
->expects($this->once())
278+
->method('setActiveEntry')
279+
->with('core_apps');
280+
281+
// When display_documentation_link is false, linkToDocs should not be called
282+
$this->urlGenerator
283+
->expects($this->never())
284+
->method('linkToDocs');
285+
286+
$providedStates = [];
287+
$this->initialState
288+
->expects($this->exactly(4))
289+
->method('provideInitialState')
290+
->willReturnCallback(function ($key, $value) use (&$providedStates) {
291+
$providedStates[$key] = $value;
292+
});
293+
294+
$this->appSettingsController->viewApps();
295+
296+
// Assert that the developer docs state was provided with an empty string
297+
$this->assertArrayHasKey('appstoreDeveloperDocs', $providedStates);
298+
$this->assertEquals('', $providedStates['appstoreDeveloperDocs']);
299+
}
300+
301+
public function testDeveloperDocumentationLinkShownByDefault(): void {
302+
$this->installer->expects($this->any())
303+
->method('isUpdateAvailable')
304+
->willReturn(false);
305+
$this->bundleFetcher->expects($this->once())->method('getBundles')->willReturn([]);
306+
$this->config
307+
->expects($this->once())
308+
->method('getSystemValueBool')
309+
->with('appstoreenabled', true)
310+
->willReturn(true);
311+
$this->appConfig
312+
->expects($this->once())
313+
->method('getValueBool')
314+
->with('settings', 'display_documentation_link', true)
315+
->willReturn(true);
316+
$this->navigationManager
317+
->expects($this->once())
318+
->method('setActiveEntry')
319+
->with('core_apps');
320+
321+
$developerDocsUrl = 'https://docs.nextcloud.com/server/latest/developer_manual/';
322+
323+
// When display_documentation_link is true (default), linkToDocs should be called
324+
$this->urlGenerator
325+
->expects($this->once())
326+
->method('linkToDocs')
327+
->with('developer-manual')
328+
->willReturn($developerDocsUrl);
329+
330+
$providedStates = [];
331+
$this->initialState
332+
->expects($this->exactly(4))
333+
->method('provideInitialState')
334+
->willReturnCallback(function ($key, $value) use (&$providedStates) {
335+
$providedStates[$key] = $value;
336+
});
337+
338+
$this->appSettingsController->viewApps();
339+
340+
// Assert that the developer docs state was provided with the correct URL
341+
$this->assertArrayHasKey('appstoreDeveloperDocs', $providedStates);
342+
$this->assertEquals($developerDocsUrl, $providedStates['appstoreDeveloperDocs']);
343+
}
246344
}

0 commit comments

Comments
 (0)