diff options
author | Christoph Wurst <christoph@winzerhof-wurst.at> | 2019-02-13 17:16:01 +0100 |
---|---|---|
committer | Roeland Jago Douma <roeland@famdouma.nl> | 2019-02-25 07:25:21 +0100 |
commit | f3023aaa85b8a168d55bd962a241e439e61105d9 (patch) | |
tree | 6823a1821403dab9b85c732b18ded91b5473f030 /apps/files_sharing | |
parent | 5df6400e287f5ba1c23dcd4749386d8bd2967d35 (diff) | |
download | nextcloud-server-f3023aaa85b8a168d55bd962a241e439e61105d9.tar.gz nextcloud-server-f3023aaa85b8a168d55bd962a241e439e61105d9.zip |
Show sharing recommendations
Signed-off-by: Christoph Wurst <christoph@winzerhof-wurst.at>
Diffstat (limited to 'apps/files_sharing')
-rw-r--r-- | apps/files_sharing/appinfo/routes.php | 5 | ||||
-rw-r--r-- | apps/files_sharing/lib/Controller/ShareesAPIController.php | 158 | ||||
-rw-r--r-- | apps/files_sharing/tests/Controller/ShareesAPIControllerTest.php | 11 |
3 files changed, 173 insertions, 1 deletions
diff --git a/apps/files_sharing/appinfo/routes.php b/apps/files_sharing/appinfo/routes.php index eea6715e57d..ce7ba409199 100644 --- a/apps/files_sharing/appinfo/routes.php +++ b/apps/files_sharing/appinfo/routes.php @@ -94,6 +94,11 @@ return [ 'url' => '/api/v1/sharees', 'verb' => 'GET', ], + [ + 'name' => 'ShareesAPI#findRecommended', + 'url' => '/api/v1/sharees_recommended', + 'verb' => 'GET', + ], /* * Remote Shares */ diff --git a/apps/files_sharing/lib/Controller/ShareesAPIController.php b/apps/files_sharing/lib/Controller/ShareesAPIController.php index c39547bdea5..a52ee88855a 100644 --- a/apps/files_sharing/lib/Controller/ShareesAPIController.php +++ b/apps/files_sharing/lib/Controller/ShareesAPIController.php @@ -29,17 +29,29 @@ declare(strict_types=1); */ namespace OCA\Files_Sharing\Controller; +use function array_filter; +use function array_slice; +use function array_values; +use Generator; +use OC\Collaboration\Collaborators\SearchResult; use OCP\AppFramework\Http\DataResponse; use OCP\AppFramework\OCS\OCSBadRequestException; use OCP\AppFramework\OCSController; use OCP\Collaboration\Collaborators\ISearch; +use OCP\Collaboration\Collaborators\ISearchResult; +use OCP\Collaboration\Collaborators\SearchResultType; use OCP\IRequest; use OCP\IConfig; use OCP\IURLGenerator; use OCP\Share; use OCP\Share\IManager; +use function usort; class ShareesAPIController extends OCSController { + + /** @var userId */ + protected $userId; + /** @var IConfig */ protected $config; @@ -87,6 +99,7 @@ class ShareesAPIController extends OCSController { private $collaboratorSearch; /** + * @param string $UserId * @param string $appName * @param IRequest $request * @param IConfig $config @@ -95,6 +108,7 @@ class ShareesAPIController extends OCSController { * @param ISearch $collaboratorSearch */ public function __construct( + $UserId, string $appName, IRequest $request, IConfig $config, @@ -103,7 +117,7 @@ class ShareesAPIController extends OCSController { ISearch $collaboratorSearch ) { parent::__construct($appName, $request); - + $this->userId = $UserId; $this->config = $config; $this->urlGenerator = $urlGenerator; $this->shareManager = $shareManager; @@ -213,6 +227,148 @@ class ShareesAPIController extends OCSController { } /** + * @param string $user + * @param int $shareType + * + * @return Generator<array<string>> + */ + private function getAllShareesByType(string $user, int $shareType): Generator { + $offset = 0; + $pageSize = 50; + + while (count($page = $this->shareManager->getSharesBy( + $user, + $shareType, + null, + false, + $pageSize, + $offset + ))) { + foreach ($page as $share) { + yield [$share->getSharedWith(), $share->getSharedWithDisplayName() ?? $share->getSharedWith()]; + } + + $offset += $pageSize; + } + } + + private function sortShareesByFrequency(array $sharees): array { + usort($sharees, function(array $s1, array $s2) { + return $s2['count'] - $s1['count']; + }); + return $sharees; + } + + private $searchResultTypeMap = [ + Share::SHARE_TYPE_USER => 'users', + Share::SHARE_TYPE_GROUP => 'groups', + Share::SHARE_TYPE_REMOTE => 'remotes', + Share::SHARE_TYPE_REMOTE_GROUP => 'remote_groups', + Share::SHARE_TYPE_EMAIL => 'emails', + ]; + + private function getAllSharees(string $user, array $shareTypes): ISearchResult { + $result = []; + foreach ($shareTypes as $shareType) { + $sharees = $this->getAllShareesByType($user, $shareType); + $shareTypeResults = []; + foreach ($sharees as list($sharee, $displayname)) { + if (!isset($this->searchResultTypeMap[$shareType])) { + continue; + } + + if (!isset($shareTypeResults[$sharee])) { + $shareTypeResults[$sharee] = [ + 'count' => 1, + 'label' => $displayname, + 'value' => [ + 'shareType' => $shareType, + 'shareWith' => $sharee, + ], + ]; + } else { + $shareTypeResults[$sharee]['count']++; + } + } + $result = array_merge($result, array_values($shareTypeResults)); + } + + $top5 = array_slice( + $this->sortShareesByFrequency($result), + 0, + 5 + ); + + $searchResult = new SearchResult(); + foreach ($this->searchResultTypeMap as $int => $str) { + $searchResult->addResultSet(new SearchResultType($str), [], []); + foreach ($top5 as $x) { + if ($x['value']['shareType'] === $int) { + $searchResult->addResultSet(new SearchResultType($str), [], [$x]); + } + } + } + return $searchResult; + } + + /** + * @NoAdminRequired + * + * @param string $itemType + * @return DataResponse + * @throws OCSBadRequestException + */ + public function findRecommended(string $itemType = null, $shareType = null): DataResponse { + $shareTypes = [ + Share::SHARE_TYPE_USER, + ]; + + if ($itemType === null) { + throw new OCSBadRequestException('Missing itemType'); + } elseif ($itemType === 'file' || $itemType === 'folder') { + if ($this->shareManager->allowGroupSharing()) { + $shareTypes[] = Share::SHARE_TYPE_GROUP; + } + + if ($this->isRemoteSharingAllowed($itemType)) { + $shareTypes[] = Share::SHARE_TYPE_REMOTE; + } + + if ($this->isRemoteGroupSharingAllowed($itemType)) { + $shareTypes[] = Share::SHARE_TYPE_REMOTE_GROUP; + } + + if ($this->shareManager->shareProviderExists(Share::SHARE_TYPE_EMAIL)) { + $shareTypes[] = Share::SHARE_TYPE_EMAIL; + } + + if ($this->shareManager->shareProviderExists(Share::SHARE_TYPE_ROOM)) { + $shareTypes[] = Share::SHARE_TYPE_ROOM; + } + } else { + $shareTypes[] = Share::SHARE_TYPE_GROUP; + $shareTypes[] = Share::SHARE_TYPE_EMAIL; + } + + // FIXME: DI + if (\OC::$server->getAppManager()->isEnabledForUser('circles') && class_exists('\OCA\Circles\ShareByCircleProvider')) { + $shareTypes[] = Share::SHARE_TYPE_CIRCLE; + } + + if (isset($_GET['shareType']) && is_array($_GET['shareType'])) { + $shareTypes = array_intersect($shareTypes, $_GET['shareType']); + sort($shareTypes); + } else if (is_numeric($shareType)) { + $shareTypes = array_intersect($shareTypes, [(int) $shareType]); + sort($shareTypes); + } + + return new DataResponse( + $this->getAllSharees($this->userId, $shareTypes)->asArray() + ); + } + + /** * Method to get out the static call for better testing * * @param string $itemType diff --git a/apps/files_sharing/tests/Controller/ShareesAPIControllerTest.php b/apps/files_sharing/tests/Controller/ShareesAPIControllerTest.php index adfb72f550a..618a1095407 100644 --- a/apps/files_sharing/tests/Controller/ShareesAPIControllerTest.php +++ b/apps/files_sharing/tests/Controller/ShareesAPIControllerTest.php @@ -50,6 +50,9 @@ class ShareesAPIControllerTest extends TestCase { /** @var ShareesAPIController */ protected $sharees; + /** @var string */ + protected $uid; + /** @var IRequest|\PHPUnit_Framework_MockObject_MockObject */ protected $request; @@ -62,6 +65,7 @@ class ShareesAPIControllerTest extends TestCase { protected function setUp() { parent::setUp(); + $this->uid = 'test123'; $this->request = $this->createMock(IRequest::class); $this->shareManager = $this->createMock(IManager::class); @@ -74,6 +78,7 @@ class ShareesAPIControllerTest extends TestCase { $this->collaboratorSearch = $this->createMock(ISearch::class); $this->sharees = new ShareesAPIController( + $this->uid, 'files_sharing', $this->request, $configMock, @@ -243,6 +248,8 @@ class ShareesAPIControllerTest extends TestCase { ->method('allowGroupSharing') ->willReturn($allowGroupSharing); + /** @var string */ + $uid = 'test123'; /** @var IRequest|\PHPUnit_Framework_MockObject_MockObject $request */ $request = $this->createMock(IRequest::class); /** @var IURLGenerator|\PHPUnit_Framework_MockObject_MockObject $urlGenerator */ @@ -251,6 +258,7 @@ class ShareesAPIControllerTest extends TestCase { /** @var \PHPUnit_Framework_MockObject_MockObject|\OCA\Files_Sharing\Controller\ShareesAPIController $sharees */ $sharees = $this->getMockBuilder('\OCA\Files_Sharing\Controller\ShareesAPIController') ->setConstructorArgs([ + $uid, 'files_sharing', $request, $config, @@ -335,6 +343,8 @@ class ShareesAPIControllerTest extends TestCase { $config->expects($this->never()) ->method('getAppValue'); + /** @var string */ + $uid = 'test123'; /** @var IRequest|\PHPUnit_Framework_MockObject_MockObject $request */ $request = $this->createMock(IRequest::class); /** @var IURLGenerator|\PHPUnit_Framework_MockObject_MockObject $urlGenerator */ @@ -343,6 +353,7 @@ class ShareesAPIControllerTest extends TestCase { /** @var \PHPUnit_Framework_MockObject_MockObject|\OCA\Files_Sharing\Controller\ShareesAPIController $sharees */ $sharees = $this->getMockBuilder('\OCA\Files_Sharing\Controller\ShareesAPIController') ->setConstructorArgs([ + $uid, 'files_sharing', $request, $config, |