config = $this->createMock(IConfig::class); $this->groupManager = $this->createMock(IGroupManager::class); $this->session = $this->createMock(IUserSession::class); $this->searchResult = new SearchResult(); $this->user = $this->getUserMock('admin', 'Administrator'); } public function instantiatePlugin(): void { // cannot be done within setUp, because dependent mocks needs to be set // up with configuration etc. first $this->plugin = new GroupPlugin( $this->config, $this->groupManager, $this->session ); } public function getUserMock(string $uid, string $displayName): IUser&MockObject { $user = $this->createMock(IUser::class); $user->expects($this->any()) ->method('getUID') ->willReturn($uid); $user->expects($this->any()) ->method('getDisplayName') ->willReturn($displayName); return $user; } protected function getGroupMock(string $gid, ?string $displayName = null, bool $hide = false): IGroup&MockObject { $group = $this->createMock(IGroup::class); $group->expects($this->any()) ->method('getGID') ->willReturn($gid); if (is_null($displayName)) { // note: this is how the Group class behaves $displayName = $gid; } $group->expects($this->any()) ->method('getDisplayName') ->willReturn($displayName); $group->method('hideFromCollaboration') ->willReturn($hide); return $group; } public static function dataGetGroups(): array { return [ ['test', false, true, false, [], [], [], [], true, false], ['test', false, false, false, [], [], [], [], true, false], // group sharing disabled ['test', false, true, true, [], [], [], [], false, false], // group without display name [ 'test', false, true, false, [['test1']], [], [], [['label' => 'test1', 'value' => ['shareType' => IShare::TYPE_GROUP, 'shareWith' => 'test1']]], true, false, ], // group with display name, search by id [ 'test', false, true, false, [['test1', 'Test One']], [], [], [['label' => 'Test One', 'value' => ['shareType' => IShare::TYPE_GROUP, 'shareWith' => 'test1']]], true, false, ], // group with display name, search by display name [ 'one', false, true, false, [['test1', 'Test One']], [], [], [['label' => 'Test One', 'value' => ['shareType' => IShare::TYPE_GROUP, 'shareWith' => 'test1']]], true, false, ], // group with display name, search by display name, exact expected [ 'Test One', false, true, false, [['test1', 'Test One']], [], [['label' => 'Test One', 'value' => ['shareType' => IShare::TYPE_GROUP, 'shareWith' => 'test1']]], [], true, false, ], [ 'test', false, false, false, [['test1']], [], [], [], true, false, ], [ 'test', false, true, false, [ ['test'], ['test1'], ], [], [['label' => 'test', 'value' => ['shareType' => IShare::TYPE_GROUP, 'shareWith' => 'test']]], [['label' => 'test1', 'value' => ['shareType' => IShare::TYPE_GROUP, 'shareWith' => 'test1']]], false, false, ], [ 'test', false, false, false, [ ['test'], ['test1'], ], [], [['label' => 'test', 'value' => ['shareType' => IShare::TYPE_GROUP, 'shareWith' => 'test']]], [], true, false, ], [ 'test', false, true, false, [ ['test0'], ['test1'], ], [], [], [ ['label' => 'test0', 'value' => ['shareType' => IShare::TYPE_GROUP, 'shareWith' => 'test0']], ['label' => 'test1', 'value' => ['shareType' => IShare::TYPE_GROUP, 'shareWith' => 'test1']], ], false, false, ], [ 'test', false, false, false, [ ['test0'], ['test1'], ], [], [], [], true, false, ], [ 'test', false, true, false, [ ['test0'], ['test1'], ], [], [ ['label' => 'test', 'value' => ['shareType' => IShare::TYPE_GROUP, 'shareWith' => 'test']], ], [ ['label' => 'test0', 'value' => ['shareType' => IShare::TYPE_GROUP, 'shareWith' => 'test0']], ['label' => 'test1', 'value' => ['shareType' => IShare::TYPE_GROUP, 'shareWith' => 'test1']], ], false, ['test'], ], [ 'test', false, false, false, [ ['test0'], ['test1'], ], [], [ ['label' => 'test', 'value' => ['shareType' => IShare::TYPE_GROUP, 'shareWith' => 'test']], ], [], true, ['test'], ], ['test', true, true, false, [], [], [], [], true, false], ['test', true, false, false, [], [], [], [], true, false], [ 'test', true, true, false, [ ['test1'], ['test2'], ], [['test1']], [], [['label' => 'test1', 'value' => ['shareType' => IShare::TYPE_GROUP, 'shareWith' => 'test1']]], false, false, ], [ 'test', true, false, false, [ ['test1'], ['test2'], ], [['test1']], [], [], true, false, ], [ 'test', true, true, false, [ ['test'], ['test1'], ], [['test']], [['label' => 'test', 'value' => ['shareType' => IShare::TYPE_GROUP, 'shareWith' => 'test']]], [], false, false, ], [ 'test', true, false, false, [ ['test'], ['test1'], ], [['test']], [['label' => 'test', 'value' => ['shareType' => IShare::TYPE_GROUP, 'shareWith' => 'test']]], [], true, false, ], [ 'test', true, true, false, [ ['test'], ['test1'], ], [['test1']], [], [['label' => 'test1', 'value' => ['shareType' => IShare::TYPE_GROUP, 'shareWith' => 'test1']]], false, false, ], [ 'test', true, false, false, [ ['test'], ['test1'], ], [['test1']], [], [], true, false, ], [ 'test', true, true, false, [ ['test'], ['test1'], ], [['test'], ['test0'], ['test1']], [['label' => 'test', 'value' => ['shareType' => IShare::TYPE_GROUP, 'shareWith' => 'test']]], [['label' => 'test1', 'value' => ['shareType' => IShare::TYPE_GROUP, 'shareWith' => 'test1']]], false, false, ], [ 'test', true, false, false, [ ['test'], ['test1'], ], [['test'], ['test0'], ['test1']], [['label' => 'test', 'value' => ['shareType' => IShare::TYPE_GROUP, 'shareWith' => 'test']]], [], true, false, ], [ 'test', true, true, false, [ ['test0'], ['test1'], ], [['test'], ['test0'], ['test1']], [], [ ['label' => 'test0', 'value' => ['shareType' => IShare::TYPE_GROUP, 'shareWith' => 'test0']], ['label' => 'test1', 'value' => ['shareType' => IShare::TYPE_GROUP, 'shareWith' => 'test1']], ], false, false, ], [ 'test', true, false, false, [ ['test0'], ['test1'], ], [['test'], ['test0'], ['test1']], [], [], true, false, ], [ 'test', true, true, false, [ ['test0'], ['test1'], ], [['test'], ['test0'], ['test1']], [ ['label' => 'test', 'value' => ['shareType' => IShare::TYPE_GROUP, 'shareWith' => 'test']], ], [ ['label' => 'test0', 'value' => ['shareType' => IShare::TYPE_GROUP, 'shareWith' => 'test0']], ['label' => 'test1', 'value' => ['shareType' => IShare::TYPE_GROUP, 'shareWith' => 'test1']], ], false, ['test'], ], [ 'test', true, false, false, [ ['test0'], ['test1'], ], [['test'], ['test0'], ['test1']], [ ['label' => 'test', 'value' => ['shareType' => IShare::TYPE_GROUP, 'shareWith' => 'test']], ], [], true, ['test'], ], [ 'test', false, false, false, [ ['test', null, true], ['test1'], ], [], [], [], true, false, ], ]; } #[DataProvider('dataGetGroups')] public function testSearch( string $searchTerm, bool $shareWithGroupOnly, bool $shareeEnumeration, bool $groupSharingDisabled, array $groupResponse, array $userGroupsResponse, array $exactExpected, array $expected, bool $reachedEnd, array|false $singleGroup, ): void { $groupResponse = array_map( fn ($args) => $this->getGroupMock(...$args), $groupResponse ); if (is_array($singleGroup)) { $singleGroup = $this->getGroupMock(...$singleGroup); } $userGroupsResponse = array_map( fn ($args) => $this->getGroupMock(...$args), $userGroupsResponse ); $this->config->expects($this->any()) ->method('getAppValue') ->willReturnCallback( function ($appName, $key, $default) use ($shareWithGroupOnly, $shareeEnumeration, $groupSharingDisabled) { if ($appName !== 'core') { return $default; } switch ($key) { case 'shareapi_only_share_with_group_members': return $shareWithGroupOnly ? 'yes' : 'no'; case 'shareapi_allow_share_dialog_user_enumeration': return $shareeEnumeration ? 'yes' : 'no'; case 'shareapi_allow_group_sharing': return $groupSharingDisabled ? 'no' : 'yes'; default: return $default; } } ); $this->instantiatePlugin(); if (!$groupSharingDisabled) { $this->groupManager->expects($this->once()) ->method('search') ->with($searchTerm, $this->limit, $this->offset) ->willReturn($groupResponse); } if ($singleGroup !== false) { $this->groupManager->expects($this->once()) ->method('get') ->with($searchTerm) ->willReturn($singleGroup); } if ($shareWithGroupOnly) { $this->session->expects($this->any()) ->method('getUser') ->willReturn($this->user); $numGetUserGroupsCalls = empty($groupResponse) ? 0 : 1; $this->groupManager->expects($this->exactly($numGetUserGroupsCalls)) ->method('getUserGroups') ->with($this->user) ->willReturn($userGroupsResponse); } $moreResults = $this->plugin->search($searchTerm, $this->limit, $this->offset, $this->searchResult); $result = $this->searchResult->asArray(); if (!$groupSharingDisabled) { $this->assertEquals($exactExpected, $result['exact']['groups']); $this->assertEquals($expected, $result['groups']); } $this->assertSame($reachedEnd, $moreResults); } }