Skip to content
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions lib/composer/composer/autoload_classmap.php
Original file line number Diff line number Diff line change
Expand Up @@ -1024,9 +1024,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',
Expand Down
2 changes: 2 additions & 0 deletions lib/composer/composer/autoload_static.php
Original file line number Diff line number Diff line change
Expand Up @@ -1065,9 +1065,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',
Expand Down
12 changes: 12 additions & 0 deletions lib/private/Teams/TeamManager.php
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
use OCA\Circles\Model\Probes\CircleProbe;
use OCP\IURLGenerator;
use OCP\Server;
use OCP\Teams\ITeamFolderProvider;
use OCP\Teams\ITeamManager;
use OCP\Teams\ITeamResourceProvider;
use OCP\Teams\Team;
Expand Down Expand Up @@ -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()) {
Expand Down
56 changes: 56 additions & 0 deletions lib/public/Teams/ITeamFolderProvider.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
<?php

declare(strict_types=1);

/**
* SPDX-FileCopyrightText: 2026 Nextcloud GmbH and Nextcloud contributors
* SPDX-License-Identifier: AGPL-3.0-or-later
*/

namespace OCP\Teams;

use OCP\AppFramework\Attribute\Consumable;
use OCP\AppFramework\Attribute\Implementable;

/**
* Provides the exclusive folder belonging to a team.
*
* Register implementations through
* {@see \OCP\AppFramework\Bootstrap\IRegistrationContext::registerTeamResourceProvider()}.
*
* @since 35.0.0
*/
Comment thread
stediefan marked this conversation as resolved.
#[Consumable(since: '35.0.0')]
#[Implementable(since: '35.0.0')]
interface ITeamFolderProvider extends ITeamResourceProvider {
/**
* Return the folder exclusively linked to the team.
*
* @since 35.0.0
*/
public function getTeamFolder(string $teamId): ?TeamFolder;

/**
* Create the exclusive folder for a team, or return its existing folder.
*
* @param Team $team The team that owns the folder.
* @param int $quota Quota in bytes; zero means unlimited.
* @since 35.0.0
*/
public function createTeamFolder(Team $team, int $quota = 0): TeamFolder;

/**
* Remove the exclusive relationship but retain the folder and its contents.
*
* @return TeamFolder|null The unlinked folder, if one existed.
* @since 35.0.0
*/
public function unlinkTeamFolder(string $teamId): ?TeamFolder;

/**
* Remove the team folder and its contents.
*
* @since 35.0.0
*/
public function removeTeamFolder(string $teamId): bool;
}
8 changes: 8 additions & 0 deletions lib/public/Teams/ITeamManager.php
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,14 @@ public function getProviders(): array;
*/
public function getProvider(string $providerId): ITeamResourceProvider;

/**
* Get the registered provider of exclusive team folders.
*
* @return ITeamFolderProvider|null Null when no folder provider is enabled.
* @since 35.0.0
*/
public function getTeamFolderProvider(): ?ITeamFolderProvider;

/**
* Returns all team resources for a given team and user
*
Expand Down
55 changes: 55 additions & 0 deletions lib/public/Teams/TeamFolder.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
<?php

declare(strict_types=1);

/**
* SPDX-FileCopyrightText: 2026 Nextcloud GmbH and Nextcloud contributors
* SPDX-License-Identifier: AGPL-3.0-or-later
*/

namespace OCP\Teams;

use OCP\AppFramework\Attribute\Consumable;

/**
* A folder exclusively linked to a team.
*
* @since 35.0.0
*/
Comment thread
stediefan marked this conversation as resolved.
#[Consumable(since: '35.0.0')]
class TeamFolder implements \JsonSerializable {
/**
* @since 35.0.0
*/
public function __construct(
private int $id,
private string $mountPoint,
) {
}

/**
* @since 35.0.0
*/
public function getId(): int {
return $this->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,
];
}
}
23 changes: 23 additions & 0 deletions tests/lib/Teams/TeamFolderTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
<?php

declare(strict_types=1);

/**
* SPDX-FileCopyrightText: 2026 Nextcloud GmbH and Nextcloud contributors
* SPDX-License-Identifier: AGPL-3.0-or-later
*/

namespace Test\Teams;

use OCP\Teams\TeamFolder;
use Test\TestCase;

class TeamFolderTest extends TestCase {
public function testSerializesFolderIdentity(): void {
$folder = new TeamFolder(42, 'Engineering');

$this->assertSame(42, $folder->getId());
$this->assertSame('Engineering', $folder->getMountPoint());
$this->assertSame(['id' => 42, 'mountPoint' => 'Engineering'], $folder->jsonSerialize());
}
}
70 changes: 70 additions & 0 deletions tests/lib/Teams/TeamManagerTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
<?php

declare(strict_types=1);

/**
* SPDX-FileCopyrightText: 2026 Nextcloud GmbH and Nextcloud contributors
* SPDX-License-Identifier: AGPL-3.0-or-later
*/

namespace Test\Teams;

use OC\AppFramework\Bootstrap\Coordinator;
use OC\Teams\TeamManager;
use OCP\IURLGenerator;
use OCP\Teams\ITeamFolderProvider;
use OCP\Teams\ITeamResourceProvider;
use Test\TestCase;

class TeamManagerTest extends TestCase {
public function testGetTeamFolderProviderReturnsNullWithoutTeamSupport(): void {
$teamManager = $this->createTeamManager();

$this->assertNull($teamManager->getTeamFolderProvider());
}

public function testGetTeamFolderProviderReturnsNullWithoutFolderProvider(): void {
$teamManager = $this->createTeamManager(true);
$this->setProviders($teamManager, [
'other' => $this->createMock(ITeamResourceProvider::class),
]);

$this->assertNull($teamManager->getTeamFolderProvider());
}

public function testGetTeamFolderProviderReturnsRegisteredFolderProvider(): void {
$teamManager = $this->createTeamManager(true);
$folderProvider = $this->createMock(ITeamFolderProvider::class);
$this->setProviders($teamManager, [
'other' => $this->createMock(ITeamResourceProvider::class),
'folder' => $folderProvider,
]);

$this->assertSame($folderProvider, $teamManager->getTeamFolderProvider());
}

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;
}
};
}

/**
* @param array<string, ITeamResourceProvider> $providers
*/
private function setProviders(TeamManager $teamManager, array $providers): void {
(new \ReflectionProperty(TeamManager::class, 'providers'))->setValue($teamManager, $providers);
}
}
Loading