Browse Source
AutoCompletion backend
AutoCompletion backend
* introduce a Controller for requests * introduce result sorting mechanism * extend Comments to retrieve commentors (actors) in a tree * add commenters sorter * add share recipients sorter Signed-off-by: Arthur Schiwon <blizzz@arthur-schiwon.de>pull/6779/head
No known key found for this signature in database
GPG Key ID: 7424F1874854DF23
21 changed files with 1090 additions and 24 deletions
-
6apps/comments/appinfo/info.xml
-
93apps/comments/lib/Collaboration/CommentersSorter.php
-
147apps/comments/tests/Unit/Collaboration/CommentersSorterTest.php
-
6apps/files_sharing/appinfo/info.xml
-
85apps/files_sharing/lib/Collaboration/ShareRecipientSorter.php
-
220apps/files_sharing/tests/Collaboration/ShareRecipientSorterTest.php
-
89core/Controller/AutoCompleteController.php
-
1core/routes.php
-
4lib/composer/composer/autoload_classmap.php
-
4lib/composer/composer/autoload_static.php
-
81lib/private/Collaboration/AutoComplete/Manager.php
-
65lib/private/Comments/Manager.php
-
12lib/private/Server.php
-
2lib/private/Share20/Manager.php
-
2lib/private/legacy/app.php
-
46lib/public/Collaboration/AutoComplete/IManager.php
-
50lib/public/Collaboration/AutoComplete/ISorter.php
-
22lib/public/Comments/ICommentsManager.php
-
84tests/Core/Controller/AutoCompleteControllerTest.php
-
14tests/lib/Comments/FakeManager.php
-
81tests/lib/Comments/ManagerTest.php
@ -0,0 +1,93 @@ |
|||
<?php |
|||
/** |
|||
* @copyright Copyright (c) 2017 Arthur Schiwon <blizzz@arthur-schiwon.de> |
|||
* |
|||
* @author Arthur Schiwon <blizzz@arthur-schiwon.de> |
|||
* |
|||
* @license GNU AGPL version 3 or any later version |
|||
* |
|||
* This program is free software: you can redistribute it and/or modify |
|||
* it under the terms of the GNU Affero General Public License as |
|||
* published by the Free Software Foundation, either version 3 of the |
|||
* License, or (at your option) any later version. |
|||
* |
|||
* This program is distributed in the hope that it will be useful, |
|||
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
|||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|||
* GNU Affero General Public License for more details. |
|||
* |
|||
* You should have received a copy of the GNU Affero General Public License |
|||
* along with this program. If not, see <http://www.gnu.org/licenses/>. |
|||
* |
|||
*/ |
|||
|
|||
namespace OCA\Comments\Collaboration; |
|||
|
|||
|
|||
use OCP\Collaboration\AutoComplete\ISorter; |
|||
use OCP\Comments\ICommentsManager; |
|||
|
|||
class CommentersSorter implements ISorter { |
|||
|
|||
/** @var ICommentsManager */ |
|||
private $commentsManager; |
|||
|
|||
public function __construct(ICommentsManager $commentsManager) { |
|||
$this->commentsManager = $commentsManager; |
|||
} |
|||
|
|||
public function getId() { |
|||
return 'commenters'; |
|||
} |
|||
|
|||
/** |
|||
* Sorts people who commented on the given item atop (descelating) of the |
|||
* others |
|||
* |
|||
* @param array $sortArray |
|||
* @param array $context |
|||
*/ |
|||
public function sort(array &$sortArray, array $context) { |
|||
$commenters = $this->retrieveCommentsInformation($context['itemType'], $context['itemId']); |
|||
if(count($commenters) === 0) { |
|||
return; |
|||
} |
|||
|
|||
foreach ($sortArray as $type => &$byType) { |
|||
if(!isset($commenters[$type])) { |
|||
continue; |
|||
} |
|||
|
|||
usort($byType, function ($a, $b) use ($commenters, $type) { |
|||
$r = $this->compare($a, $b, $commenters[$type]); |
|||
return $r; |
|||
}); |
|||
|
|||
$s = ''; |
|||
} |
|||
} |
|||
|
|||
/** |
|||
* @param $type |
|||
* @param $id |
|||
* @return array |
|||
*/ |
|||
protected function retrieveCommentsInformation($type, $id) { |
|||
$comments = $this->commentsManager->getForObject($type, $id, 1); |
|||
if(count($comments) === 0) { |
|||
return []; |
|||
} |
|||
|
|||
return $this->commentsManager->getActorsInTree($comments[0]->getTopmostParentId()); |
|||
} |
|||
|
|||
protected function compare(array $a, array $b, array $commenters) { |
|||
$a = $a['value']['shareWith']; |
|||
$b = $b['value']['shareWith']; |
|||
|
|||
$valueA = isset($commenters[$a]) ? $commenters[$a] : 0; |
|||
$valueB = isset($commenters[$b]) ? $commenters[$b] : 0; |
|||
|
|||
return $valueB - $valueA; |
|||
} |
|||
} |
|||
@ -0,0 +1,147 @@ |
|||
<?php |
|||
/** |
|||
* @copyright Copyright (c) 2017 Arthur Schiwon <blizzz@arthur-schiwon.de> |
|||
* |
|||
* @author Arthur Schiwon <blizzz@arthur-schiwon.de> |
|||
* |
|||
* @license GNU AGPL version 3 or any later version |
|||
* |
|||
* This program is free software: you can redistribute it and/or modify |
|||
* it under the terms of the GNU Affero General Public License as |
|||
* published by the Free Software Foundation, either version 3 of the |
|||
* License, or (at your option) any later version. |
|||
* |
|||
* This program is distributed in the hope that it will be useful, |
|||
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
|||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|||
* GNU Affero General Public License for more details. |
|||
* |
|||
* You should have received a copy of the GNU Affero General Public License |
|||
* along with this program. If not, see <http://www.gnu.org/licenses/>. |
|||
* |
|||
*/ |
|||
|
|||
namespace OCA\Comments\Tests\Unit\Collaboration; |
|||
|
|||
|
|||
use OCA\Comments\Collaboration\CommentersSorter; |
|||
use OCP\Comments\IComment; |
|||
use OCP\Comments\ICommentsManager; |
|||
use Test\TestCase; |
|||
|
|||
class CommentersSorterTest extends TestCase { |
|||
/** @var ICommentsManager|\PHPUnit_Framework_MockObject_MockObject */ |
|||
protected $commentsManager; |
|||
/** @var CommentersSorter */ |
|||
protected $sorter; |
|||
|
|||
public function setUp() { |
|||
parent::setUp(); |
|||
|
|||
$this->commentsManager = $this->createMock(ICommentsManager::class); |
|||
|
|||
$this->sorter = new CommentersSorter($this->commentsManager); |
|||
} |
|||
|
|||
/** |
|||
* @dataProvider sortDataProvider |
|||
* @param $data |
|||
*/ |
|||
public function testSort($data) { |
|||
$this->commentsManager->expects($this->once()) |
|||
->method('getForObject') |
|||
->willReturn([$this->createMock(IComment::class)]); |
|||
|
|||
$this->commentsManager->expects($this->once()) |
|||
->method('getActorsInTree') |
|||
->willReturn($data['actors']); |
|||
|
|||
$workArray = $data['input']; |
|||
$this->sorter->sort($workArray, ['itemType' => 'files', 'itemId' => '24']); |
|||
|
|||
$this->assertSame($data['expected'], $workArray); |
|||
} |
|||
|
|||
public function sortDataProvider() { |
|||
return [[ |
|||
[ |
|||
#1 – sort properly and otherwise keep existing order
|
|||
'actors' => ['users' => ['celia' => 3, 'darius' => 7, 'faruk' => 5, 'gail' => 5], 'bots' => ['r2-d2' => 8]], |
|||
'input' => [ |
|||
'users' => |
|||
[ |
|||
['value' => ['shareWith' => 'alice']], |
|||
['value' => ['shareWith' => 'bob']], |
|||
['value' => ['shareWith' => 'celia']], |
|||
['value' => ['shareWith' => 'darius']], |
|||
['value' => ['shareWith' => 'elena']], |
|||
['value' => ['shareWith' => 'faruk']], |
|||
['value' => ['shareWith' => 'gail']], |
|||
], |
|||
'bots' => [ |
|||
['value' => ['shareWith' => 'c-3po']], |
|||
['value' => ['shareWith' => 'r2-d2']], |
|||
] |
|||
], |
|||
'expected' => [ |
|||
'users' => |
|||
[ |
|||
['value' => ['shareWith' => 'darius']], |
|||
['value' => ['shareWith' => 'faruk']], |
|||
['value' => ['shareWith' => 'gail']], |
|||
['value' => ['shareWith' => 'celia']], |
|||
['value' => ['shareWith' => 'alice']], |
|||
['value' => ['shareWith' => 'bob']], |
|||
['value' => ['shareWith' => 'elena']], |
|||
], |
|||
'bots' => [ |
|||
['value' => ['shareWith' => 'r2-d2']], |
|||
['value' => ['shareWith' => 'c-3po']], |
|||
] |
|||
], |
|||
], |
|||
[ |
|||
#2 – no commentors, input equals output
|
|||
'actors' => [], |
|||
'input' => [ |
|||
'users' => |
|||
[ |
|||
['value' => ['shareWith' => 'alice']], |
|||
['value' => ['shareWith' => 'bob']], |
|||
['value' => ['shareWith' => 'celia']], |
|||
['value' => ['shareWith' => 'darius']], |
|||
['value' => ['shareWith' => 'elena']], |
|||
['value' => ['shareWith' => 'faruk']], |
|||
['value' => ['shareWith' => 'gail']], |
|||
], |
|||
'bots' => [ |
|||
['value' => ['shareWith' => 'c-3po']], |
|||
['value' => ['shareWith' => 'r2-d2']], |
|||
] |
|||
], |
|||
'expected' => [ |
|||
'users' => |
|||
[ |
|||
['value' => ['shareWith' => 'alice']], |
|||
['value' => ['shareWith' => 'bob']], |
|||
['value' => ['shareWith' => 'celia']], |
|||
['value' => ['shareWith' => 'darius']], |
|||
['value' => ['shareWith' => 'elena']], |
|||
['value' => ['shareWith' => 'faruk']], |
|||
['value' => ['shareWith' => 'gail']], |
|||
], |
|||
'bots' => [ |
|||
['value' => ['shareWith' => 'c-3po']], |
|||
['value' => ['shareWith' => 'r2-d2']], |
|||
] |
|||
], |
|||
], |
|||
[ |
|||
#3 – no nothing
|
|||
'actors' => [], |
|||
'input' => [], |
|||
'expected' => [], |
|||
], |
|||
]]; |
|||
} |
|||
} |
|||
@ -0,0 +1,85 @@ |
|||
<?php |
|||
/** |
|||
* @copyright Copyright (c) 2017 Arthur Schiwon <blizzz@arthur-schiwon.de> |
|||
* |
|||
* @author Arthur Schiwon <blizzz@arthur-schiwon.de> |
|||
* |
|||
* @license GNU AGPL version 3 or any later version |
|||
* |
|||
* This program is free software: you can redistribute it and/or modify |
|||
* it under the terms of the GNU Affero General Public License as |
|||
* published by the Free Software Foundation, either version 3 of the |
|||
* License, or (at your option) any later version. |
|||
* |
|||
* This program is distributed in the hope that it will be useful, |
|||
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
|||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|||
* GNU Affero General Public License for more details. |
|||
* |
|||
* You should have received a copy of the GNU Affero General Public License |
|||
* along with this program. If not, see <http://www.gnu.org/licenses/>. |
|||
* |
|||
*/ |
|||
|
|||
namespace OCA\Files_Sharing\Collaboration; |
|||
|
|||
|
|||
use OCP\Collaboration\AutoComplete\ISorter; |
|||
use OCP\Files\Folder; |
|||
use OCP\Files\Node; |
|||
use OCP\Share\IManager; |
|||
|
|||
class ShareRecipientSorter implements ISorter { |
|||
|
|||
/** @var IManager */ |
|||
private $shareManager; |
|||
/** @var Folder */ |
|||
private $userFolder; |
|||
|
|||
public function __construct(IManager $shareManager, Folder $userFolder) { |
|||
$this->shareManager = $shareManager; |
|||
$this->userFolder = $userFolder; |
|||
} |
|||
|
|||
public function getId() { |
|||
return 'share-recipients'; |
|||
} |
|||
|
|||
public function sort(array &$sortArray, array $context) { |
|||
// let's be tolerant. Comments uses "files" by default, other usages are often singular
|
|||
if($context['itemType'] !== 'files' && $context['itemType'] !== 'file') { |
|||
return; |
|||
} |
|||
/** @var Node[] $nodes */ |
|||
$nodes = $this->userFolder->getById((int)$context['itemId']); |
|||
if(count($nodes) === 0) { |
|||
return; |
|||
} |
|||
$al = $this->shareManager->getAccessList($nodes[0]); |
|||
|
|||
foreach ($sortArray as $type => &$byType) { |
|||
if(!isset($al[$type]) || !is_array($al[$type])) { |
|||
continue; |
|||
} |
|||
usort($byType, function ($a, $b) use ($al, $type) { |
|||
return $this->compare($a, $b, $al[$type]); |
|||
}); |
|||
} |
|||
} |
|||
|
|||
/** |
|||
* @param array $a |
|||
* @param array $b |
|||
* @param array $al |
|||
* @return int |
|||
*/ |
|||
protected function compare(array $a, array $b, array $al) { |
|||
$a = $a['value']['shareWith']; |
|||
$b = $b['value']['shareWith']; |
|||
|
|||
$valueA = (int)in_array($a, $al, true); |
|||
$valueB = (int)in_array($b, $al, true); |
|||
|
|||
return $valueB - $valueA; |
|||
} |
|||
} |
|||
@ -0,0 +1,220 @@ |
|||
<?php |
|||
/** |
|||
* @copyright Copyright (c) 2017 Arthur Schiwon <blizzz@arthur-schiwon.de> |
|||
* |
|||
* @author Arthur Schiwon <blizzz@arthur-schiwon.de> |
|||
* |
|||
* @license GNU AGPL version 3 or any later version |
|||
* |
|||
* This program is free software: you can redistribute it and/or modify |
|||
* it under the terms of the GNU Affero General Public License as |
|||
* published by the Free Software Foundation, either version 3 of the |
|||
* License, or (at your option) any later version. |
|||
* |
|||
* This program is distributed in the hope that it will be useful, |
|||
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
|||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|||
* GNU Affero General Public License for more details. |
|||
* |
|||
* You should have received a copy of the GNU Affero General Public License |
|||
* along with this program. If not, see <http://www.gnu.org/licenses/>. |
|||
* |
|||
*/ |
|||
|
|||
namespace OCA\Files_Sharing\Tests\Collaboration; |
|||
|
|||
|
|||
use OCA\Files_Sharing\Collaboration\ShareRecipientSorter; |
|||
use OCP\Files\Folder; |
|||
use OCP\Files\Node; |
|||
use OCP\Share\IManager; |
|||
use Test\TestCase; |
|||
|
|||
class ShareRecipientSorterTest extends TestCase { |
|||
/** @var IManager|\PHPUnit_Framework_MockObject_MockObject */ |
|||
protected $shareManager; |
|||
/** @var Folder|\PHPUnit_Framework_MockObject_MockObject */ |
|||
protected $userFolder; |
|||
/** @var ShareRecipientSorter */ |
|||
protected $sorter; |
|||
|
|||
public function setUp() { |
|||
parent::setUp(); |
|||
|
|||
$this->shareManager = $this->createMock(IManager::class); |
|||
$this->userFolder = $this->createMock(Folder::class); |
|||
|
|||
$this->sorter = new ShareRecipientSorter($this->shareManager, $this->userFolder); |
|||
} |
|||
|
|||
/** |
|||
* @dataProvider sortDataProvider |
|||
* @param $data |
|||
*/ |
|||
public function testSort($data) { |
|||
$node = $this->createMock(Node::class); |
|||
|
|||
if ($data['context']['itemType'] === 'files') { |
|||
$this->userFolder->expects($this->once()) |
|||
->method('getById') |
|||
->with($data['context']['itemId']) |
|||
->willReturn([$node]); |
|||
|
|||
$this->shareManager->expects($this->once()) |
|||
->method('getAccessList') |
|||
->with($node) |
|||
->willReturn($data['accessList']); |
|||
} else { |
|||
$this->userFolder->expects($this->never()) |
|||
->method('getById'); |
|||
$this->shareManager->expects($this->never()) |
|||
->method('getAccessList'); |
|||
} |
|||
|
|||
$workArray = $data['input']; |
|||
$this->sorter->sort($workArray, $data['context']); |
|||
|
|||
$this->assertSame($data['expected'], $workArray); |
|||
} |
|||
|
|||
public function testSortNoNodes() { |
|||
$this->userFolder->expects($this->once()) |
|||
->method('getById') |
|||
->willReturn([]); |
|||
|
|||
$this->shareManager->expects($this->never()) |
|||
->method('getAccessList'); |
|||
|
|||
$originalArray = ['users' => [ |
|||
['value' => ['shareWith' => 'alice']], |
|||
['value' => ['shareWith' => 'bob']], |
|||
]]; |
|||
$workArray = $originalArray; |
|||
$this->sorter->sort($workArray, ['itemType' => 'files', 'itemId' => 404]); |
|||
|
|||
$this->assertEquals($originalArray, $workArray); |
|||
} |
|||
|
|||
public function sortDataProvider() { |
|||
return [[ |
|||
[ |
|||
#1 – sort properly and otherwise keep existing order
|
|||
'context' => ['itemType' => 'files', 'itemId' => 42], |
|||
'accessList' => ['users' => ['celia', 'darius', 'faruk', 'gail'], 'bots' => ['r2-d2']], |
|||
'input' => [ |
|||
'users' => |
|||
[ |
|||
['value' => ['shareWith' => 'alice']], |
|||
['value' => ['shareWith' => 'bob']], |
|||
['value' => ['shareWith' => 'celia']], |
|||
['value' => ['shareWith' => 'darius']], |
|||
['value' => ['shareWith' => 'elena']], |
|||
['value' => ['shareWith' => 'faruk']], |
|||
['value' => ['shareWith' => 'gail']], |
|||
], |
|||
'bots' => [ |
|||
['value' => ['shareWith' => 'c-3po']], |
|||
['value' => ['shareWith' => 'r2-d2']], |
|||
] |
|||
], |
|||
'expected' => [ |
|||
'users' => |
|||
[ |
|||
['value' => ['shareWith' => 'celia']], |
|||
['value' => ['shareWith' => 'darius']], |
|||
['value' => ['shareWith' => 'faruk']], |
|||
['value' => ['shareWith' => 'gail']], |
|||
['value' => ['shareWith' => 'alice']], |
|||
['value' => ['shareWith' => 'bob']], |
|||
['value' => ['shareWith' => 'elena']], |
|||
], |
|||
'bots' => [ |
|||
['value' => ['shareWith' => 'r2-d2']], |
|||
['value' => ['shareWith' => 'c-3po']], |
|||
] |
|||
], |
|||
], |
|||
[ |
|||
# 2 – no recipients
|
|||
'context' => ['itemType' => 'files', 'itemId' => 42], |
|||
'accessList' => ['users' => false], |
|||
'input' => [ |
|||
'users' => |
|||
[ |
|||
['value' => ['shareWith' => 'alice']], |
|||
['value' => ['shareWith' => 'bob']], |
|||
['value' => ['shareWith' => 'celia']], |
|||
['value' => ['shareWith' => 'darius']], |
|||
['value' => ['shareWith' => 'elena']], |
|||
['value' => ['shareWith' => 'faruk']], |
|||
['value' => ['shareWith' => 'gail']], |
|||
], |
|||
'bots' => [ |
|||
['value' => ['shareWith' => 'c-3po']], |
|||
['value' => ['shareWith' => 'r2-d2']], |
|||
] |
|||
], |
|||
'expected' => [ |
|||
'users' => |
|||
[ |
|||
['value' => ['shareWith' => 'alice']], |
|||
['value' => ['shareWith' => 'bob']], |
|||
['value' => ['shareWith' => 'celia']], |
|||
['value' => ['shareWith' => 'darius']], |
|||
['value' => ['shareWith' => 'elena']], |
|||
['value' => ['shareWith' => 'faruk']], |
|||
['value' => ['shareWith' => 'gail']], |
|||
], |
|||
'bots' => [ |
|||
['value' => ['shareWith' => 'c-3po']], |
|||
['value' => ['shareWith' => 'r2-d2']], |
|||
] |
|||
], |
|||
], |
|||
[ |
|||
#3 – unsupported item type
|
|||
'context' => ['itemType' => 'announcements', 'itemId' => 42], |
|||
'accessList' => null, // not needed
|
|||
'input' => [ |
|||
'users' => |
|||
[ |
|||
['value' => ['shareWith' => 'alice']], |
|||
['value' => ['shareWith' => 'bob']], |
|||
['value' => ['shareWith' => 'celia']], |
|||
['value' => ['shareWith' => 'darius']], |
|||
['value' => ['shareWith' => 'elena']], |
|||
['value' => ['shareWith' => 'faruk']], |
|||
['value' => ['shareWith' => 'gail']], |
|||
], |
|||
'bots' => [ |
|||
['value' => ['shareWith' => 'c-3po']], |
|||
['value' => ['shareWith' => 'r2-d2']], |
|||
] |
|||
], |
|||
'expected' => [ |
|||
'users' => |
|||
[ |
|||
['value' => ['shareWith' => 'alice']], |
|||
['value' => ['shareWith' => 'bob']], |
|||
['value' => ['shareWith' => 'celia']], |
|||
['value' => ['shareWith' => 'darius']], |
|||
['value' => ['shareWith' => 'elena']], |
|||
['value' => ['shareWith' => 'faruk']], |
|||
['value' => ['shareWith' => 'gail']], |
|||
], |
|||
'bots' => [ |
|||
['value' => ['shareWith' => 'c-3po']], |
|||
['value' => ['shareWith' => 'r2-d2']], |
|||
] |
|||
], |
|||
], |
|||
[ |
|||
#4 – no nothing
|
|||
'context' => ['itemType' => 'files', 'itemId' => 42], |
|||
'accessList' => [], |
|||
'input' => [], |
|||
'expected' => [], |
|||
], |
|||
]]; |
|||
} |
|||
} |
|||
@ -0,0 +1,89 @@ |
|||
<?php |
|||
/** |
|||
* @copyright Copyright (c) 2017 Arthur Schiwon <blizzz@arthur-schiwon.de> |
|||
* |
|||
* @author Arthur Schiwon <blizzz@arthur-schiwon.de> |
|||
* |
|||
* @license GNU AGPL version 3 or any later version |
|||
* |
|||
* This program is free software: you can redistribute it and/or modify |
|||
* it under the terms of the GNU Affero General Public License as |
|||
* published by the Free Software Foundation, either version 3 of the |
|||
* License, or (at your option) any later version. |
|||
* |
|||
* This program is distributed in the hope that it will be useful, |
|||
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
|||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|||
* GNU Affero General Public License for more details. |
|||
* |
|||
* You should have received a copy of the GNU Affero General Public License |
|||
* along with this program. If not, see <http://www.gnu.org/licenses/>. |
|||
* |
|||
*/ |
|||
|
|||
namespace OC\Core\Controller; |
|||
|
|||
use OCP\AppFramework\Controller; |
|||
use OCP\AppFramework\Http\DataResponse; |
|||
use OCP\Collaboration\AutoComplete\IManager; |
|||
use OCP\Collaboration\Collaborators\ISearch; |
|||
use OCP\IRequest; |
|||
use OCP\Share; |
|||
|
|||
class AutoCompleteController extends Controller { |
|||
/** @var ISearch */ |
|||
private $collaboratorSearch; |
|||
/** @var IManager */ |
|||
private $autoCompleteManager; |
|||
|
|||
public function __construct($appName, IRequest $request, ISearch $collaboratorSearch, IManager $autoCompleteManager) { |
|||
parent::__construct($appName, $request); |
|||
|
|||
$this->collaboratorSearch = $collaboratorSearch; |
|||
$this->autoCompleteManager = $autoCompleteManager; |
|||
} |
|||
|
|||
/** |
|||
* @NoAdminRequired |
|||
* |
|||
* @param string $itemType |
|||
* @param string $itemId |
|||
* @param string|null $sorter can be piped, top prio first, e.g.: "commenters|share-recipients" |
|||
* @param array $shareTypes |
|||
* @return DataResponse |
|||
*/ |
|||
public function get($itemType, $itemId, $sorter = null, $shareTypes = [Share::SHARE_TYPE_USER]) { |
|||
// if enumeration/user listings are disabled, we'll receive an empty
|
|||
// result from search() – thus nothing else to do here.
|
|||
list($results,) = $this->collaboratorSearch->search('', $shareTypes, false, 20, 0); |
|||
|
|||
// there won't be exact matches without a search string
|
|||
unset($results['exact']); |
|||
|
|||
$sorters = array_reverse(explode('|', $sorter)); |
|||
$this->autoCompleteManager->runSorters($sorters, $results, [ |
|||
'itemType' => $itemType, |
|||
'itemId' => $itemId, |
|||
]); |
|||
|
|||
// transform to expected format
|
|||
$results = $this->prepareResultArray($results); |
|||
|
|||
return new DataResponse($results); |
|||
} |
|||
|
|||
|
|||
protected function prepareResultArray(array $results) { |
|||
$output = []; |
|||
foreach ($results as $type => $subResult) { |
|||
foreach ($subResult as $result) { |
|||
$output[] = [ |
|||
'id' => $result['value']['shareWith'], |
|||
'label' => $result['label'], |
|||
'source' => $type, |
|||
]; |
|||
} |
|||
} |
|||
return $output; |
|||
} |
|||
} |
|||
@ -0,0 +1,81 @@ |
|||
<?php |
|||
/** |
|||
* @copyright Copyright (c) 2017 Arthur Schiwon <blizzz@arthur-schiwon.de> |
|||
* |
|||
* @author Arthur Schiwon <blizzz@arthur-schiwon.de> |
|||
* |
|||
* @license GNU AGPL version 3 or any later version |
|||
* |
|||
* This program is free software: you can redistribute it and/or modify |
|||
* it under the terms of the GNU Affero General Public License as |
|||
* published by the Free Software Foundation, either version 3 of the |
|||
* License, or (at your option) any later version. |
|||
* |
|||
* This program is distributed in the hope that it will be useful, |
|||
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
|||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|||
* GNU Affero General Public License for more details. |
|||
* |
|||
* You should have received a copy of the GNU Affero General Public License |
|||
* along with this program. If not, see <http://www.gnu.org/licenses/>. |
|||
* |
|||
*/ |
|||
|
|||
namespace OC\Collaboration\AutoComplete; |
|||
|
|||
use OCP\Collaboration\AutoComplete\IManager; |
|||
use OCP\Collaboration\AutoComplete\ISorter; |
|||
use OCP\IServerContainer; |
|||
|
|||
class Manager implements IManager { |
|||
/** @var string[] */ |
|||
protected $sorters =[]; |
|||
|
|||
/** @var ISorter[] */ |
|||
protected $sorterInstances = []; |
|||
/** @var IServerContainer */ |
|||
private $c; |
|||
|
|||
public function __construct(IServerContainer $container) { |
|||
$this->c = $container; |
|||
} |
|||
|
|||
public function runSorters(array $sorters, array &$sortArray, array $context) { |
|||
$sorterInstances = $this->getSorters(); |
|||
while($sorter = array_shift($sorters)) { |
|||
if(isset($sorterInstances[$sorter])) { |
|||
$sorterInstances[$sorter]->sort($sortArray, $context); |
|||
} else { |
|||
$this->c->getLogger()->warning('No sorter for ID "{id}", skipping', [ |
|||
'app' => 'core', 'id' => $sorter |
|||
]); |
|||
} |
|||
} |
|||
} |
|||
|
|||
public function registerSorter($className) { |
|||
$sorters[] = $className; |
|||
} |
|||
|
|||
protected function getSorters() { |
|||
if(count($this->sorterInstances) === 0) { |
|||
foreach ($this->sorters as $sorter) { |
|||
/** @var ISorter $instance */ |
|||
$instance = $this->c->resolve($sorter); |
|||
if(!$instance instanceof ISorter) { |
|||
$this->c->getLogger()->notice('Skipping sorter which is not an instance of ISorter. Class name: {class}', |
|||
['app' => 'core', 'class' => $sorter]); |
|||
continue; |
|||
} |
|||
$sorterId = trim($instance->getId()); |
|||
if(trim($sorterId) === '') { |
|||
$this->c->getLogger()->notice('Skipping sorter with empty ID. Class name: {class}', |
|||
['app' => 'core', 'class' => $sorter]); |
|||
continue; |
|||
} |
|||
$this->sorterInstances[$sorterId] = $instance; |
|||
} |
|||
} |
|||
return $this->sorterInstances; |
|||
} |
|||
} |
|||
@ -0,0 +1,46 @@ |
|||
<?php |
|||
/** |
|||
* @copyright Copyright (c) 2017 Arthur Schiwon <blizzz@arthur-schiwon.de> |
|||
* |
|||
* @author Arthur Schiwon <blizzz@arthur-schiwon.de> |
|||
* |
|||
* @license GNU AGPL version 3 or any later version |
|||
* |
|||
* This program is free software: you can redistribute it and/or modify |
|||
* it under the terms of the GNU Affero General Public License as |
|||
* published by the Free Software Foundation, either version 3 of the |
|||
* License, or (at your option) any later version. |
|||
* |
|||
* This program is distributed in the hope that it will be useful, |
|||
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
|||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|||
* GNU Affero General Public License for more details. |
|||
* |
|||
* You should have received a copy of the GNU Affero General Public License |
|||
* along with this program. If not, see <http://www.gnu.org/licenses/>. |
|||
* |
|||
*/ |
|||
|
|||
namespace OCP\Collaboration\AutoComplete; |
|||
|
|||
/** |
|||
* Interface IManager |
|||
* |
|||
* @package OCP\Collaboration\AutoComplete |
|||
* @since 13.0.0 |
|||
*/ |
|||
interface IManager { |
|||
/** |
|||
* @param string $className – class name of the ISorter implementation |
|||
* @since 13.0.0 |
|||
*/ |
|||
public function registerSorter($className); |
|||
|
|||
/** |
|||
* @param array $sorters list of sorter IDs, seperated by "|" |
|||
* @param array $sortArray array representation of OCP\Collaboration\Collaborators\ISearchResult |
|||
* @param array $context context info of the search, keys: itemType, itemId |
|||
* @since 13.0.0 |
|||
*/ |
|||
public function runSorters(array $sorters, array &$sortArray, array $context); |
|||
} |
|||
@ -0,0 +1,50 @@ |
|||
<?php |
|||
/** |
|||
* @copyright Copyright (c) 2017 Arthur Schiwon <blizzz@arthur-schiwon.de> |
|||
* |
|||
* @author Arthur Schiwon <blizzz@arthur-schiwon.de> |
|||
* |
|||
* @license GNU AGPL version 3 or any later version |
|||
* |
|||
* This program is free software: you can redistribute it and/or modify |
|||
* it under the terms of the GNU Affero General Public License as |
|||
* published by the Free Software Foundation, either version 3 of the |
|||
* License, or (at your option) any later version. |
|||
* |
|||
* This program is distributed in the hope that it will be useful, |
|||
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
|||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|||
* GNU Affero General Public License for more details. |
|||
* |
|||
* You should have received a copy of the GNU Affero General Public License |
|||
* along with this program. If not, see <http://www.gnu.org/licenses/>. |
|||
* |
|||
*/ |
|||
|
|||
namespace OCP\Collaboration\AutoComplete; |
|||
|
|||
/** |
|||
* Interface ISorter |
|||
* |
|||
* Sorts the list of .e.g users for auto completion |
|||
* |
|||
* @package OCP\Collaboration\AutoComplete |
|||
* @since 13.0.0 |
|||
*/ |
|||
interface ISorter { |
|||
|
|||
/** |
|||
* @return string The ID of the sorter, e.g. commenters |
|||
* @since 13.0.0 |
|||
*/ |
|||
public function getId(); |
|||
|
|||
/** |
|||
* executes the sort action |
|||
* |
|||
* @param array $sortArray the array to be sorted, provided as reference |
|||
* @param array $context carries key 'itemType' and 'itemId' of the source object (e.g. a file) |
|||
* @since 13.0.0 |
|||
*/ |
|||
public function sort(array &$sortArray, array $context); |
|||
} |
|||
@ -0,0 +1,84 @@ |
|||
<?php |
|||
/** |
|||
* @copyright Copyright (c) 2017 Arthur Schiwon <blizzz@arthur-schiwon.de> |
|||
* |
|||
* @author Arthur Schiwon <blizzz@arthur-schiwon.de> |
|||
* |
|||
* @license GNU AGPL version 3 or any later version |
|||
* |
|||
* This program is free software: you can redistribute it and/or modify |
|||
* it under the terms of the GNU Affero General Public License as |
|||
* published by the Free Software Foundation, either version 3 of the |
|||
* License, or (at your option) any later version. |
|||
* |
|||
* This program is distributed in the hope that it will be useful, |
|||
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
|||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|||
* GNU Affero General Public License for more details. |
|||
* |
|||
* You should have received a copy of the GNU Affero General Public License |
|||
* along with this program. If not, see <http://www.gnu.org/licenses/>. |
|||
* |
|||
*/ |
|||
|
|||
namespace Tests\Core\Controller; |
|||
|
|||
|
|||
use OC\Core\Controller\AutoCompleteController; |
|||
use OCP\Collaboration\AutoComplete\IManager; |
|||
use OCP\Collaboration\Collaborators\ISearch; |
|||
use OCP\IRequest; |
|||
use Test\TestCase; |
|||
|
|||
class AutoCompleteControllerTest extends TestCase { |
|||
/** @var ISearch|\PHPUnit_Framework_MockObject_MockObject */ |
|||
protected $collaboratorSearch; |
|||
/** @var IManager|\PHPUnit_Framework_MockObject_MockObject */ |
|||
protected $autoCompleteManager; |
|||
/** @var AutoCompleteController */ |
|||
protected $controller; |
|||
|
|||
protected function setUp() { |
|||
parent::setUp(); |
|||
|
|||
/** @var IRequest $request */ |
|||
$request = $this->createMock(IRequest::class); |
|||
$this->collaboratorSearch = $this->createMock(ISearch::class); |
|||
$this->autoCompleteManager = $this->createMock(IManager::class); |
|||
|
|||
$this->controller = new AutoCompleteController( |
|||
'core', |
|||
$request, |
|||
$this->collaboratorSearch, |
|||
$this->autoCompleteManager |
|||
); |
|||
} |
|||
|
|||
public function testGet() { |
|||
$searchResults = [ |
|||
'exact' => [ |
|||
'users' => [], |
|||
'robots' => [], |
|||
], |
|||
'users' => [ |
|||
['label' => 'Alice A.', 'value' => ['shareWith' => 'alice']], |
|||
['label' => 'Bob Y.', 'value' => ['shareWith' => 'bob']], |
|||
], |
|||
]; |
|||
|
|||
$expected = [ |
|||
[ 'id' => 'alice', 'label' => 'Alice A.', 'source' => 'users'], |
|||
[ 'id' => 'bob', 'label' => 'Bob Y.', 'source' => 'users'], |
|||
]; |
|||
|
|||
$this->collaboratorSearch->expects($this->once()) |
|||
->method('search') |
|||
->willReturn([$searchResults, false]); |
|||
|
|||
$response = $this->controller->get('files', '42', null); |
|||
|
|||
$list = $response->getData(); |
|||
$this->assertEquals($expected, $list); // has better error output…
|
|||
$this->assertSame($expected, $list); |
|||
} |
|||
} |
|||
Write
Preview
Loading…
Cancel
Save
Reference in new issue