aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorprovokateurin <kate@provokateurin.de>2024-07-19 08:35:47 +0200
committerprovokateurin <kate@provokateurin.de>2024-07-19 08:59:47 +0200
commit815fe7fb8be639096b12a3bc4989b261a6ac5d7b (patch)
tree89904995259decc14b840e05a44d614a6a2193f4
parented1d8d162c935c122ccbcac1ad45f945da46ea23 (diff)
downloadnextcloud-server-815fe7fb8be639096b12a3bc4989b261a6ac5d7b.tar.gz
nextcloud-server-815fe7fb8be639096b12a3bc4989b261a6ac5d7b.zip
feat(Capabilities): Add IFeature
Signed-off-by: provokateurin <kate@provokateurin.de>
-rw-r--r--lib/composer/composer/autoload_classmap.php1
-rw-r--r--lib/composer/composer/autoload_static.php1
-rw-r--r--lib/private/CapabilitiesManager.php33
-rw-r--r--lib/public/Capabilities/IFeature.php30
-rw-r--r--tests/lib/CapabilitiesManagerTest.php69
5 files changed, 131 insertions, 3 deletions
diff --git a/lib/composer/composer/autoload_classmap.php b/lib/composer/composer/autoload_classmap.php
index fbc61bcb1a6..d277254d607 100644
--- a/lib/composer/composer/autoload_classmap.php
+++ b/lib/composer/composer/autoload_classmap.php
@@ -178,6 +178,7 @@ return array(
'OCP\\Calendar\\Room\\IRoom' => $baseDir . '/lib/public/Calendar/Room/IRoom.php',
'OCP\\Calendar\\Room\\IRoomMetadata' => $baseDir . '/lib/public/Calendar/Room/IRoomMetadata.php',
'OCP\\Capabilities\\ICapability' => $baseDir . '/lib/public/Capabilities/ICapability.php',
+ 'OCP\\Capabilities\\IFeature' => $baseDir . '/lib/public/Capabilities/IFeature.php',
'OCP\\Capabilities\\IInitialStateExcludedCapability' => $baseDir . '/lib/public/Capabilities/IInitialStateExcludedCapability.php',
'OCP\\Capabilities\\IPublicCapability' => $baseDir . '/lib/public/Capabilities/IPublicCapability.php',
'OCP\\Collaboration\\AutoComplete\\AutoCompleteEvent' => $baseDir . '/lib/public/Collaboration/AutoComplete/AutoCompleteEvent.php',
diff --git a/lib/composer/composer/autoload_static.php b/lib/composer/composer/autoload_static.php
index dd25d62f7e3..d29355b1998 100644
--- a/lib/composer/composer/autoload_static.php
+++ b/lib/composer/composer/autoload_static.php
@@ -211,6 +211,7 @@ class ComposerStaticInit749170dad3f5e7f9ca158f5a9f04f6a2
'OCP\\Calendar\\Room\\IRoom' => __DIR__ . '/../../..' . '/lib/public/Calendar/Room/IRoom.php',
'OCP\\Calendar\\Room\\IRoomMetadata' => __DIR__ . '/../../..' . '/lib/public/Calendar/Room/IRoomMetadata.php',
'OCP\\Capabilities\\ICapability' => __DIR__ . '/../../..' . '/lib/public/Capabilities/ICapability.php',
+ 'OCP\\Capabilities\\IFeature' => __DIR__ . '/../../..' . '/lib/public/Capabilities/IFeature.php',
'OCP\\Capabilities\\IInitialStateExcludedCapability' => __DIR__ . '/../../..' . '/lib/public/Capabilities/IInitialStateExcludedCapability.php',
'OCP\\Capabilities\\IPublicCapability' => __DIR__ . '/../../..' . '/lib/public/Capabilities/IPublicCapability.php',
'OCP\\Collaboration\\AutoComplete\\AutoCompleteEvent' => __DIR__ . '/../../..' . '/lib/public/Collaboration/AutoComplete/AutoCompleteEvent.php',
diff --git a/lib/private/CapabilitiesManager.php b/lib/private/CapabilitiesManager.php
index d7bf25f078a..d3f36690f76 100644
--- a/lib/private/CapabilitiesManager.php
+++ b/lib/private/CapabilitiesManager.php
@@ -6,10 +6,12 @@ declare(strict_types=1);
* SPDX-FileCopyrightText: 2016 ownCloud, Inc.
* SPDX-License-Identifier: AGPL-3.0-only
*/
+
namespace OC;
use OCP\AppFramework\QueryException;
use OCP\Capabilities\ICapability;
+use OCP\Capabilities\IFeature;
use OCP\Capabilities\IInitialStateExcludedCapability;
use OCP\Capabilities\IPublicCapability;
use Psr\Log\LoggerInterface;
@@ -35,10 +37,10 @@ class CapabilitiesManager {
* Get an array of al the capabilities that are registered at this manager
*
* @param bool $public get public capabilities only
- * @throws \InvalidArgumentException
* @return array<string, mixed>
+ * @throws \InvalidArgumentException
*/
- public function getCapabilities(bool $public = false, bool $initialState = false) : array {
+ public function getCapabilities(bool $public = false, bool $initialState = false): array {
$capabilities = [];
foreach ($this->capabilities as $capability) {
try {
@@ -88,6 +90,33 @@ class CapabilitiesManager {
}
/**
+ * @return array<string, list<string>>
+ */
+ public function getFeatures(): array {
+ $features = [];
+ foreach ($this->capabilities as $capability) {
+ try {
+ $c = $capability();
+ } catch (QueryException $e) {
+ $this->logger->error('CapabilitiesManager', [
+ 'exception' => $e,
+ ]);
+ continue;
+ }
+
+ if ($c instanceof ICapability) {
+ if ($c instanceof IFeature) {
+ $features = array_merge_recursive($features, $c->getFeatures());
+ }
+ } else {
+ throw new \InvalidArgumentException('The given Capability (' . get_class($c) . ') does not implement the ICapability interface');
+ }
+ }
+
+ return $features;
+ }
+
+ /**
* In order to improve lazy loading a closure can be registered which will be called in case
* capabilities are actually requested
*
diff --git a/lib/public/Capabilities/IFeature.php b/lib/public/Capabilities/IFeature.php
new file mode 100644
index 00000000000..27e2e097672
--- /dev/null
+++ b/lib/public/Capabilities/IFeature.php
@@ -0,0 +1,30 @@
+<?php
+
+namespace OCP\Capabilities;
+
+/**
+ * Interface for apps to expose their available features.
+ *
+ * @since 30.0.0
+ */
+interface IFeature {
+ /**
+ * Returns the available features.
+ *
+ * ```php
+ * return [
+ * 'myapp' => [
+ * 'feature1',
+ * 'feature2',
+ * ],
+ * 'otherapp' => [
+ * 'feature3',
+ * ],
+ * ];
+ * ```
+ *
+ * @return array<string, list<string>>
+ * @since 30.0.0
+ */
+ public function getFeatures(): array;
+}
diff --git a/tests/lib/CapabilitiesManagerTest.php b/tests/lib/CapabilitiesManagerTest.php
index 14b83e3dda3..18c23308336 100644
--- a/tests/lib/CapabilitiesManagerTest.php
+++ b/tests/lib/CapabilitiesManagerTest.php
@@ -7,9 +7,11 @@
namespace Test;
+use InvalidArgumentException;
use OC\CapabilitiesManager;
use OCP\AppFramework\QueryException;
use OCP\Capabilities\ICapability;
+use OCP\Capabilities\IFeature;
use OCP\Capabilities\IPublicCapability;
use Psr\Log\LoggerInterface;
@@ -68,7 +70,7 @@ class CapabilitiesManagerTest extends TestCase {
* Test that we need something that implents ICapability
*/
public function testNoICapability() {
- $this->expectException(\InvalidArgumentException::class);
+ $this->expectException(InvalidArgumentException::class);
$this->expectExceptionMessage('The given Capability (Test\\NoCapability) does not implement the ICapability interface');
$this->manager->registerCapability(function () {
@@ -140,6 +142,24 @@ class CapabilitiesManagerTest extends TestCase {
$this->assertEquals([], $res);
}
+
+
+ public function testFeatures() {
+ $this->manager->registerCapability(fn () => new FeatureFoo());
+
+ $res = $this->manager->getFeatures();
+ $this->assertEquals(['foo' => ['123', '456']], $res);
+
+ $this->manager->registerCapability(fn () => new FeatureBar());
+
+ $res = $this->manager->getFeatures();
+ $this->assertEquals(['foo' => ['123', '456'], 'bar' => ['789']], $res);
+
+ $this->manager->registerCapability(fn () => new FeatureFooBar());
+
+ $res = $this->manager->getFeatures();
+ $this->assertEquals(['foo' => ['123', '456', '789'], 'bar' => ['789', '123', '456']], $res);
+ }
}
class SimpleCapability implements ICapability {
@@ -193,3 +213,50 @@ class DeepCapability implements ICapability {
];
}
}
+
+class FeatureFoo implements ICapability, IFeature {
+ public function getCapabilities() {
+ return [];
+ }
+
+ public function getFeatures(): array {
+ return [
+ 'foo' => [
+ '123',
+ '456',
+ ],
+ ];
+ }
+}
+
+class FeatureBar implements ICapability, IFeature {
+ public function getCapabilities() {
+ return [];
+ }
+
+ public function getFeatures(): array {
+ return [
+ 'bar' => [
+ '789',
+ ],
+ ];
+ }
+}
+
+class FeatureFooBar implements ICapability, IFeature {
+ public function getCapabilities() {
+ return [];
+ }
+
+ public function getFeatures(): array {
+ return [
+ 'foo' => [
+ '789',
+ ],
+ 'bar' => [
+ '123',
+ '456',
+ ],
+ ];
+ }
+}