feat: hide caldav server settings if no app uses the caldav backend

Signed-off-by: Richard Steinmetz <richard@steinmetz.cloud>
pull/46510/head
Richard Steinmetz 2024-07-13 16:51:16 +07:00
parent 70dd8d513b
commit e42bceac9f
No known key found for this signature in database
GPG Key ID: 27137D9E7D273FB2
12 changed files with 138 additions and 12 deletions

@ -6,6 +6,7 @@
namespace OCA\DAV\Settings; namespace OCA\DAV\Settings;
use OCA\DAV\AppInfo\Application; use OCA\DAV\AppInfo\Application;
use OCP\App\IAppManager;
use OCP\AppFramework\Http\TemplateResponse; use OCP\AppFramework\Http\TemplateResponse;
use OCP\AppFramework\Services\IInitialState; use OCP\AppFramework\Services\IInitialState;
use OCP\IConfig; use OCP\IConfig;
@ -21,6 +22,7 @@ class CalDAVSettings implements IDelegatedSettings {
private $initialState; private $initialState;
private IURLGenerator $urlGenerator; private IURLGenerator $urlGenerator;
private IAppManager $appManager;
private const defaults = [ private const defaults = [
'sendInvitations' => 'yes', 'sendInvitations' => 'yes',
@ -36,10 +38,11 @@ class CalDAVSettings implements IDelegatedSettings {
* @param IConfig $config * @param IConfig $config
* @param IInitialState $initialState * @param IInitialState $initialState
*/ */
public function __construct(IConfig $config, IInitialState $initialState, IURLGenerator $urlGenerator) { public function __construct(IConfig $config, IInitialState $initialState, IURLGenerator $urlGenerator, IAppManager $appManager) {
$this->config = $config; $this->config = $config;
$this->initialState = $initialState; $this->initialState = $initialState;
$this->urlGenerator = $urlGenerator; $this->urlGenerator = $urlGenerator;
$this->appManager = $appManager;
} }
public function getForm(): TemplateResponse { public function getForm(): TemplateResponse {
@ -51,10 +54,11 @@ class CalDAVSettings implements IDelegatedSettings {
return new TemplateResponse(Application::APP_ID, 'settings-admin-caldav'); return new TemplateResponse(Application::APP_ID, 'settings-admin-caldav');
} }
/** public function getSection(): ?string {
* @return string if (!$this->appManager->isBackendRequired(IAppManager::BACKEND_CALDAV)) {
*/ return null;
public function getSection() { }
return 'groupware'; return 'groupware';
} }

@ -6,6 +6,7 @@
namespace OCA\DAV\Tests\Unit\DAV\Settings; namespace OCA\DAV\Tests\Unit\DAV\Settings;
use OCA\DAV\Settings\CalDAVSettings; use OCA\DAV\Settings\CalDAVSettings;
use OCP\App\IAppManager;
use OCP\AppFramework\Http\TemplateResponse; use OCP\AppFramework\Http\TemplateResponse;
use OCP\AppFramework\Services\IInitialState; use OCP\AppFramework\Services\IInitialState;
use OCP\IConfig; use OCP\IConfig;
@ -24,6 +25,9 @@ class CalDAVSettingsTest extends TestCase {
/** @var IURLGenerator|MockObject */ /** @var IURLGenerator|MockObject */
private $urlGenerator; private $urlGenerator;
/** @var IAppManager|MockObject */
private $appManager;
private CalDAVSettings $settings; private CalDAVSettings $settings;
protected function setUp(): void { protected function setUp(): void {
@ -32,7 +36,8 @@ class CalDAVSettingsTest extends TestCase {
$this->config = $this->createMock(IConfig::class); $this->config = $this->createMock(IConfig::class);
$this->initialState = $this->createMock(IInitialState::class); $this->initialState = $this->createMock(IInitialState::class);
$this->urlGenerator = $this->createMock(IURLGenerator::class); $this->urlGenerator = $this->createMock(IURLGenerator::class);
$this->settings = new CalDAVSettings($this->config, $this->initialState, $this->urlGenerator); $this->appManager = $this->createMock(IAppManager::class);
$this->settings = new CalDAVSettings($this->config, $this->initialState, $this->urlGenerator, $this->appManager);
} }
public function testGetForm(): void { public function testGetForm(): void {
@ -65,10 +70,23 @@ class CalDAVSettingsTest extends TestCase {
} }
public function testGetSection(): void { public function testGetSection(): void {
$this->appManager->expects(self::once())
->method('isBackendRequired')
->with(IAppManager::BACKEND_CALDAV)
->willReturn(true);
$this->assertEquals('groupware', $this->settings->getSection()); $this->assertEquals('groupware', $this->settings->getSection());
} }
public function testGetSectionWithoutCaldavBackend(): void {
$this->appManager->expects(self::once())
->method('isBackendRequired')
->with(IAppManager::BACKEND_CALDAV)
->willReturn(false);
$this->assertEquals(null, $this->settings->getSection());
}
public function testGetPriority(): void { public function testGetPriority(): void {
$this->assertEquals(10, $this->settings->getPriority()); $this->assertEquals(10, $this->settings->getPriority());
} }
} }

@ -875,4 +875,16 @@ class AppManager implements IAppManager {
$this->config->setSystemValue('defaultapp', join(',', $defaultApps)); $this->config->setSystemValue('defaultapp', join(',', $defaultApps));
} }
public function isBackendRequired(string $backend): bool {
foreach ($this->appInfos as $appInfo) {
foreach ($appInfo['dependencies']['backend'] as $appBackend) {
if ($backend === $appBackend) {
return true;
}
}
}
return false;
}
} }

@ -113,6 +113,12 @@ class InfoParser {
if (!array_key_exists('personal-section', $array['settings'])) { if (!array_key_exists('personal-section', $array['settings'])) {
$array['settings']['personal-section'] = []; $array['settings']['personal-section'] = [];
} }
if (!array_key_exists('dependencies', $array)) {
$array['dependencies'] = [];
}
if (!array_key_exists('backend', $array['dependencies'])) {
$array['dependencies']['backend'] = [];
}
if (array_key_exists('types', $array)) { if (array_key_exists('types', $array)) {
if (is_array($array['types'])) { if (is_array($array['types'])) {
@ -177,10 +183,12 @@ class InfoParser {
if (isset($array['settings']['personal-section']) && !is_array($array['settings']['personal-section'])) { if (isset($array['settings']['personal-section']) && !is_array($array['settings']['personal-section'])) {
$array['settings']['personal-section'] = [$array['settings']['personal-section']]; $array['settings']['personal-section'] = [$array['settings']['personal-section']];
} }
if (isset($array['navigations']['navigation']) && $this->isNavigationItem($array['navigations']['navigation'])) { if (isset($array['navigations']['navigation']) && $this->isNavigationItem($array['navigations']['navigation'])) {
$array['navigations']['navigation'] = [$array['navigations']['navigation']]; $array['navigations']['navigation'] = [$array['navigations']['navigation']];
} }
if (isset($array['dependencies']['backend']) && !is_array($array['dependencies']['backend'])) {
$array['dependencies']['backend'] = [$array['dependencies']['backend']];
}
if ($this->cache !== null) { if ($this->cache !== null) {
$this->cache->set($fileCacheKey, json_encode($array)); $this->cache->set($fileCacheKey, json_encode($array));

@ -19,6 +19,11 @@ use OCP\IUser;
* @since 8.0.0 * @since 8.0.0
*/ */
interface IAppManager { interface IAppManager {
/**
* @since 30.0.0
*/
public const BACKEND_CALDAV = 'caldav';
/** /**
* Returns the app information from "appinfo/info.xml". * Returns the app information from "appinfo/info.xml".
* *
@ -261,4 +266,14 @@ interface IAppManager {
* @since 28.0.0 * @since 28.0.0
*/ */
public function setDefaultApps(array $defaultApps): void; public function setDefaultApps(array $defaultApps): void;
/**
* Check whether the given backend is required by at least one app.
*
* @param self::BACKEND_* $backend Name of the backend, one of `self::BACKEND_*`
* @return bool True if at least one app requires the backend
*
* @since 30.0.0
*/
public function isBackendRequired(string $backend): bool;
} }

@ -575,6 +575,8 @@
maxOccurs="1"/> maxOccurs="1"/>
<xs:element name="architecture" type="architecture" minOccurs="0" <xs:element name="architecture" type="architecture" minOccurs="0"
maxOccurs="unbounded"/> maxOccurs="unbounded"/>
<xs:element name="backend" type="backend" minOccurs="0"
maxOccurs="unbounded"/>
</xs:sequence> </xs:sequence>
</xs:complexType> </xs:complexType>
@ -757,4 +759,9 @@
</xs:restriction> </xs:restriction>
</xs:simpleType> </xs:simpleType>
<xs:simpleType name="backend">
<xs:restriction base="xs:string">
<xs:enumeration value="caldav"/>
</xs:restriction>
</xs:simpleType>
</xs:schema> </xs:schema>

@ -563,6 +563,8 @@
maxOccurs="1"/> maxOccurs="1"/>
<xs:element name="architecture" type="architecture" minOccurs="0" <xs:element name="architecture" type="architecture" minOccurs="0"
maxOccurs="unbounded"/> maxOccurs="unbounded"/>
<xs:element name="backend" type="backend" minOccurs="0"
maxOccurs="unbounded"/>
</xs:sequence> </xs:sequence>
</xs:complexType> </xs:complexType>
@ -737,4 +739,10 @@
value="[a-zA-Z_][0-9a-zA-Z_]*(\\[a-zA-Z_][0-9a-zA-Z_]*)*"/> value="[a-zA-Z_][0-9a-zA-Z_]*(\\[a-zA-Z_][0-9a-zA-Z_]*)*"/>
</xs:restriction> </xs:restriction>
</xs:simpleType> </xs:simpleType>
<xs:simpleType name="backend">
<xs:restriction base="xs:string">
<xs:enumeration value="caldav"/>
</xs:restriction>
</xs:simpleType>
</xs:schema> </xs:schema>

@ -65,7 +65,10 @@
"min-version": "7.0.1", "min-version": "7.0.1",
"max-version": "8" "max-version": "8"
} }
} },
"backend": [
"caldav"
]
}, },
"repair-steps": { "repair-steps": {
"install": [], "install": [],

@ -29,7 +29,8 @@
"min-version": "16", "min-version": "16",
"max-version": "16" "max-version": "16"
} }
} },
"backend": []
}, },
"background-jobs": [ "background-jobs": [
"OCA\\Activity\\BackgroundJob\\EmailNotification", "OCA\\Activity\\BackgroundJob\\EmailNotification",

@ -29,7 +29,8 @@
"min-version": "16", "min-version": "16",
"max-version": "16" "max-version": "16"
} }
} },
"backend": []
}, },
"background-jobs": [ "background-jobs": [
"OCA\\Activity\\BackgroundJob\\EmailNotification", "OCA\\Activity\\BackgroundJob\\EmailNotification",

@ -34,5 +34,6 @@
<lib>curl</lib> <lib>curl</lib>
<os>Linux</os> <os>Linux</os>
<owncloud min-version="7.0.1" max-version="8" /> <owncloud min-version="7.0.1" max-version="8" />
<backend>caldav</backend>
</dependencies> </dependencies>
</info> </info>

@ -885,4 +885,52 @@ class AppManagerTest extends TestCase {
$this->assertEquals($expectedApp, $this->manager->getDefaultAppForUser(null, $withFallbacks)); $this->assertEquals($expectedApp, $this->manager->getDefaultAppForUser(null, $withFallbacks));
} }
public static function isBackendRequiredDataProvider(): array {
return [
// backend available
[
'caldav',
['app1' => ['caldav']],
true,
],
[
'caldav',
['app1' => [], 'app2' => ['foo'], 'app3' => ['caldav']],
true,
],
// backend not available
[
'caldav',
['app3' => [], 'app1' => ['foo'], 'app2' => ['bar', 'baz']],
false,
],
// no app available
[
'caldav',
[],
false,
],
];
}
/**
* @dataProvider isBackendRequiredDataProvider
*/
public function testIsBackendRequired(
string $backend,
array $appBackends,
bool $expected,
): void {
$appInfoData = array_map(
static fn (array $backends) => ['dependencies' => ['backend' => $backends]],
$appBackends,
);
$reflection = new \ReflectionClass($this->manager);
$property = $reflection->getProperty('appInfos');
$property->setValue($this->manager, $appInfoData);
$this->assertEquals($expected, $this->manager->isBackendRequired($backend));
}
} }