From 203d0295c0002661020e18d08c2c56d7757984aa Mon Sep 17 00:00:00 2001 From: Stefan Dietrich <5716289+stediefan@users.noreply.github.com> Date: Fri, 24 Jul 2026 12:05:05 +0200 Subject: [PATCH 1/2] feat: introduce a function to bind a teamfolder to a team Assisted by: GitHub Copilot:Claude Sonnet 5 Assisted by: GitHub Copilot:GPT-5.6 Terra Assisted by: GitHub Copilot:Kimi K2.7 Code Signed-off-by: Stefan Dietrich <5716289+stediefan@users.noreply.github.com> --- lib/private/Teams/TeamManager.php | 12 +++++ lib/public/Teams/ITeamFolderProvider.php | 51 ++++++++++++++++++++ lib/public/Teams/ITeamManager.php | 8 ++++ lib/public/Teams/TeamFolder.php | 52 ++++++++++++++++++++ tests/lib/Teams/TeamFolderTest.php | 23 +++++++++ tests/lib/Teams/TeamManagerTest.php | 61 ++++++++++++++++++++++++ 6 files changed, 207 insertions(+) create mode 100644 lib/public/Teams/ITeamFolderProvider.php create mode 100644 lib/public/Teams/TeamFolder.php create mode 100644 tests/lib/Teams/TeamFolderTest.php create mode 100644 tests/lib/Teams/TeamManagerTest.php diff --git a/lib/private/Teams/TeamManager.php b/lib/private/Teams/TeamManager.php index c466b1d20c088..ab3471cd45953 100644 --- a/lib/private/Teams/TeamManager.php +++ b/lib/private/Teams/TeamManager.php @@ -16,6 +16,7 @@ use OCP\IURLGenerator; use OCP\Server; use OCP\Teams\ITeamManager; +use OCP\Teams\ITeamFolderProvider; use OCP\Teams\ITeamResourceProvider; use OCP\Teams\Team; use Psr\Container\ContainerExceptionInterface; @@ -70,6 +71,17 @@ public function getProvider(string $providerId): ITeamResourceProvider { throw new \RuntimeException('No provider found for id ' . $providerId); } + #[\Override] + public function getTeamFolderProvider(): ?ITeamFolderProvider { + foreach ($this->getProviders() as $provider) { + if ($provider instanceof ITeamFolderProvider) { + return $provider; + } + } + + return null; + } + #[\Override] public function getSharedWith(string $teamId, string $userId): array { if (!$this->hasTeamSupport()) { diff --git a/lib/public/Teams/ITeamFolderProvider.php b/lib/public/Teams/ITeamFolderProvider.php new file mode 100644 index 0000000000000..1f78bc18f014d --- /dev/null +++ b/lib/public/Teams/ITeamFolderProvider.php @@ -0,0 +1,51 @@ +id; + } + + /** + * @since 35.0.0 + */ + public function getMountPoint(): string { + return $this->mountPoint; + } + + /** + * @return array{id: int, mountPoint: string} + * @since 35.0.0 + */ + #[\Override] + public function jsonSerialize(): array { + return [ + 'id' => $this->id, + 'mountPoint' => $this->mountPoint, + ]; + } +} diff --git a/tests/lib/Teams/TeamFolderTest.php b/tests/lib/Teams/TeamFolderTest.php new file mode 100644 index 0000000000000..0b5397dbf224e --- /dev/null +++ b/tests/lib/Teams/TeamFolderTest.php @@ -0,0 +1,23 @@ +assertSame(42, $folder->getId()); + $this->assertSame('Engineering', $folder->getMountPoint()); + $this->assertSame(['id' => 42, 'mountPoint' => 'Engineering'], $folder->jsonSerialize()); + } +} diff --git a/tests/lib/Teams/TeamManagerTest.php b/tests/lib/Teams/TeamManagerTest.php new file mode 100644 index 0000000000000..45d233e50e30e --- /dev/null +++ b/tests/lib/Teams/TeamManagerTest.php @@ -0,0 +1,61 @@ +createTeamManager(null); + + $this->assertNull($teamManager->getTeamFolderProvider()); + } + + public function testGetTeamFolderProviderReturnsNullWithoutFolderProvider(): void { + $teamManager = $this->createTeamManager($this->createMock(CirclesManager::class)); + $this->setProviders($teamManager, [ + 'other' => $this->createMock(ITeamResourceProvider::class), + ]); + + $this->assertNull($teamManager->getTeamFolderProvider()); + } + + public function testGetTeamFolderProviderReturnsRegisteredFolderProvider(): void { + $teamManager = $this->createTeamManager($this->createMock(CirclesManager::class)); + $folderProvider = $this->createMock(ITeamFolderProvider::class); + $this->setProviders($teamManager, [ + 'other' => $this->createMock(ITeamResourceProvider::class), + 'folder' => $folderProvider, + ]); + + $this->assertSame($folderProvider, $teamManager->getTeamFolderProvider()); + } + + private function createTeamManager(?CirclesManager $circlesManager): TeamManager { + return new TeamManager( + $this->createMock(Coordinator::class), + $this->createMock(IURLGenerator::class), + $circlesManager, + ); + } + + /** + * @param array $providers + */ + private function setProviders(TeamManager $teamManager, array $providers): void { + (new \ReflectionProperty(TeamManager::class, 'providers'))->setValue($teamManager, $providers); + } +} \ No newline at end of file From eac1aa3eb2fb4837c61c98a70f6d2cb55c8374c9 Mon Sep 17 00:00:00 2001 From: Stefan Dietrich <5716289+stediefan@users.noreply.github.com> Date: Mon, 27 Jul 2026 08:56:17 +0200 Subject: [PATCH 2/2] fix(teams): add consumable and implementable annotations fix: tests for TeamFolderProvider and TeamManager Assisted-by: GitHub Copilot:GPT-5.6 Terra Signed-off-by: Stefan Dietrich <5716289+stediefan@users.noreply.github.com> --- .../dav/composer/composer/autoload_static.php | 4 +-- lib/composer/composer/autoload_classmap.php | 2 ++ lib/composer/composer/autoload_static.php | 2 ++ lib/private/Teams/TeamManager.php | 2 +- lib/public/Teams/ITeamFolderProvider.php | 5 +++ lib/public/Teams/TeamFolder.php | 3 ++ tests/lib/Teams/TeamManagerTest.php | 31 ++++++++++++------- 7 files changed, 35 insertions(+), 14 deletions(-) diff --git a/apps/dav/composer/composer/autoload_static.php b/apps/dav/composer/composer/autoload_static.php index fad494f1c6fe6..5aa979e007acc 100644 --- a/apps/dav/composer/composer/autoload_static.php +++ b/apps/dav/composer/composer/autoload_static.php @@ -7,14 +7,14 @@ class ComposerStaticInitDAV { public static $prefixLengthsPsr4 = array ( - 'O' => + 'O' => array ( 'OCA\\DAV\\' => 8, ), ); public static $prefixDirsPsr4 = array ( - 'OCA\\DAV\\' => + 'OCA\\DAV\\' => array ( 0 => __DIR__ . '/..' . '/../lib', ), diff --git a/lib/composer/composer/autoload_classmap.php b/lib/composer/composer/autoload_classmap.php index beafb4700c69d..45bb5ce0e007a 100644 --- a/lib/composer/composer/autoload_classmap.php +++ b/lib/composer/composer/autoload_classmap.php @@ -1023,9 +1023,11 @@ 'OCP\\TaskProcessing\\TaskTypes\\TextToTextSummary' => $baseDir . '/lib/public/TaskProcessing/TaskTypes/TextToTextSummary.php', 'OCP\\TaskProcessing\\TaskTypes\\TextToTextTopics' => $baseDir . '/lib/public/TaskProcessing/TaskTypes/TextToTextTopics.php', 'OCP\\TaskProcessing\\TaskTypes\\TextToTextTranslate' => $baseDir . '/lib/public/TaskProcessing/TaskTypes/TextToTextTranslate.php', + 'OCP\\Teams\\ITeamFolderProvider' => $baseDir . '/lib/public/Teams/ITeamFolderProvider.php', 'OCP\\Teams\\ITeamManager' => $baseDir . '/lib/public/Teams/ITeamManager.php', 'OCP\\Teams\\ITeamResourceProvider' => $baseDir . '/lib/public/Teams/ITeamResourceProvider.php', 'OCP\\Teams\\Team' => $baseDir . '/lib/public/Teams/Team.php', + 'OCP\\Teams\\TeamFolder' => $baseDir . '/lib/public/Teams/TeamFolder.php', 'OCP\\Teams\\TeamResource' => $baseDir . '/lib/public/Teams/TeamResource.php', 'OCP\\Template' => $baseDir . '/lib/public/Template.php', 'OCP\\Template\\ITemplate' => $baseDir . '/lib/public/Template/ITemplate.php', diff --git a/lib/composer/composer/autoload_static.php b/lib/composer/composer/autoload_static.php index e024c1fb44b9f..c3d8ee4f403a1 100644 --- a/lib/composer/composer/autoload_static.php +++ b/lib/composer/composer/autoload_static.php @@ -1064,9 +1064,11 @@ class ComposerStaticInit749170dad3f5e7f9ca158f5a9f04f6a2 'OCP\\TaskProcessing\\TaskTypes\\TextToTextSummary' => __DIR__ . '/../../..' . '/lib/public/TaskProcessing/TaskTypes/TextToTextSummary.php', 'OCP\\TaskProcessing\\TaskTypes\\TextToTextTopics' => __DIR__ . '/../../..' . '/lib/public/TaskProcessing/TaskTypes/TextToTextTopics.php', 'OCP\\TaskProcessing\\TaskTypes\\TextToTextTranslate' => __DIR__ . '/../../..' . '/lib/public/TaskProcessing/TaskTypes/TextToTextTranslate.php', + 'OCP\\Teams\\ITeamFolderProvider' => __DIR__ . '/../../..' . '/lib/public/Teams/ITeamFolderProvider.php', 'OCP\\Teams\\ITeamManager' => __DIR__ . '/../../..' . '/lib/public/Teams/ITeamManager.php', 'OCP\\Teams\\ITeamResourceProvider' => __DIR__ . '/../../..' . '/lib/public/Teams/ITeamResourceProvider.php', 'OCP\\Teams\\Team' => __DIR__ . '/../../..' . '/lib/public/Teams/Team.php', + 'OCP\\Teams\\TeamFolder' => __DIR__ . '/../../..' . '/lib/public/Teams/TeamFolder.php', 'OCP\\Teams\\TeamResource' => __DIR__ . '/../../..' . '/lib/public/Teams/TeamResource.php', 'OCP\\Template' => __DIR__ . '/../../..' . '/lib/public/Template.php', 'OCP\\Template\\ITemplate' => __DIR__ . '/../../..' . '/lib/public/Template/ITemplate.php', diff --git a/lib/private/Teams/TeamManager.php b/lib/private/Teams/TeamManager.php index ab3471cd45953..d17aefe36223b 100644 --- a/lib/private/Teams/TeamManager.php +++ b/lib/private/Teams/TeamManager.php @@ -15,8 +15,8 @@ use OCA\Circles\Model\Probes\CircleProbe; use OCP\IURLGenerator; use OCP\Server; -use OCP\Teams\ITeamManager; use OCP\Teams\ITeamFolderProvider; +use OCP\Teams\ITeamManager; use OCP\Teams\ITeamResourceProvider; use OCP\Teams\Team; use Psr\Container\ContainerExceptionInterface; diff --git a/lib/public/Teams/ITeamFolderProvider.php b/lib/public/Teams/ITeamFolderProvider.php index 1f78bc18f014d..58b1b6f19ca41 100644 --- a/lib/public/Teams/ITeamFolderProvider.php +++ b/lib/public/Teams/ITeamFolderProvider.php @@ -9,6 +9,9 @@ namespace OCP\Teams; +use OCP\AppFramework\Attribute\Consumable; +use OCP\AppFramework\Attribute\Implementable; + /** * Provides the exclusive folder belonging to a team. * @@ -17,6 +20,8 @@ * * @since 35.0.0 */ +#[Consumable(since: '35.0.0')] +#[Implementable(since: '35.0.0')] interface ITeamFolderProvider extends ITeamResourceProvider { /** * Return the folder exclusively linked to the team. diff --git a/lib/public/Teams/TeamFolder.php b/lib/public/Teams/TeamFolder.php index 330a8bfd4ca4b..0d87a11b46f36 100644 --- a/lib/public/Teams/TeamFolder.php +++ b/lib/public/Teams/TeamFolder.php @@ -9,11 +9,14 @@ namespace OCP\Teams; +use OCP\AppFramework\Attribute\Consumable; + /** * A folder exclusively linked to a team. * * @since 35.0.0 */ +#[Consumable(since: '35.0.0')] class TeamFolder implements \JsonSerializable { /** * @since 35.0.0 diff --git a/tests/lib/Teams/TeamManagerTest.php b/tests/lib/Teams/TeamManagerTest.php index 45d233e50e30e..b5b1a42aca124 100644 --- a/tests/lib/Teams/TeamManagerTest.php +++ b/tests/lib/Teams/TeamManagerTest.php @@ -11,7 +11,6 @@ use OC\AppFramework\Bootstrap\Coordinator; use OC\Teams\TeamManager; -use OCA\Circles\CirclesManager; use OCP\IURLGenerator; use OCP\Teams\ITeamFolderProvider; use OCP\Teams\ITeamResourceProvider; @@ -19,13 +18,13 @@ class TeamManagerTest extends TestCase { public function testGetTeamFolderProviderReturnsNullWithoutTeamSupport(): void { - $teamManager = $this->createTeamManager(null); + $teamManager = $this->createTeamManager(); $this->assertNull($teamManager->getTeamFolderProvider()); } public function testGetTeamFolderProviderReturnsNullWithoutFolderProvider(): void { - $teamManager = $this->createTeamManager($this->createMock(CirclesManager::class)); + $teamManager = $this->createTeamManager(true); $this->setProviders($teamManager, [ 'other' => $this->createMock(ITeamResourceProvider::class), ]); @@ -34,7 +33,7 @@ public function testGetTeamFolderProviderReturnsNullWithoutFolderProvider(): voi } public function testGetTeamFolderProviderReturnsRegisteredFolderProvider(): void { - $teamManager = $this->createTeamManager($this->createMock(CirclesManager::class)); + $teamManager = $this->createTeamManager(true); $folderProvider = $this->createMock(ITeamFolderProvider::class); $this->setProviders($teamManager, [ 'other' => $this->createMock(ITeamResourceProvider::class), @@ -44,12 +43,22 @@ public function testGetTeamFolderProviderReturnsRegisteredFolderProvider(): void $this->assertSame($folderProvider, $teamManager->getTeamFolderProvider()); } - private function createTeamManager(?CirclesManager $circlesManager): TeamManager { - return new TeamManager( - $this->createMock(Coordinator::class), - $this->createMock(IURLGenerator::class), - $circlesManager, - ); + private function createTeamManager(bool $hasTeamSupport = false): TeamManager { + return new class($this->createMock(Coordinator::class), $this->createMock(IURLGenerator::class), null, $hasTeamSupport, ) extends TeamManager { + public function __construct( + Coordinator $bootContext, + IURLGenerator $urlGenerator, + null $circlesManager, + private bool $hasTeamSupport, + ) { + parent::__construct($bootContext, $urlGenerator, $circlesManager); + } + + #[\Override] + public function hasTeamSupport(): bool { + return $this->hasTeamSupport; + } + }; } /** @@ -58,4 +67,4 @@ private function createTeamManager(?CirclesManager $circlesManager): TeamManager private function setProviders(TeamManager $teamManager, array $providers): void { (new \ReflectionProperty(TeamManager::class, 'providers'))->setValue($teamManager, $providers); } -} \ No newline at end of file +}