diff options
author | Joas Schilling <coding@schilljs.com> | 2021-03-17 09:02:37 +0100 |
---|---|---|
committer | Joas Schilling <coding@schilljs.com> | 2021-03-17 09:51:31 +0100 |
commit | 9a189bc710a971bea5edb4807914a3978356e66b (patch) | |
tree | c9451bc47f58b1eb61459b1d7a7b6006ec65d095 /lib/private | |
parent | f82edda9c190462132f5042a177e7fa413291330 (diff) | |
download | nextcloud-server-9a189bc710a971bea5edb4807914a3978356e66b.tar.gz nextcloud-server-9a189bc710a971bea5edb4807914a3978356e66b.zip |
Improve search results when only phonebook-matches can we autocompleted
Signed-off-by: Joas Schilling <coding@schilljs.com>
Diffstat (limited to 'lib/private')
-rw-r--r-- | lib/private/Collaboration/Collaborators/UserPlugin.php | 6 | ||||
-rw-r--r-- | lib/private/User/Database.php | 44 | ||||
-rw-r--r-- | lib/private/User/Manager.php | 36 |
3 files changed, 84 insertions, 2 deletions
diff --git a/lib/private/Collaboration/Collaborators/UserPlugin.php b/lib/private/Collaboration/Collaborators/UserPlugin.php index 06a8c6f0efd..c2132048b2f 100644 --- a/lib/private/Collaboration/Collaborators/UserPlugin.php +++ b/lib/private/Collaboration/Collaborators/UserPlugin.php @@ -116,7 +116,11 @@ class UserPlugin implements ISearchPlugin { } } else { // Search in all users - $usersTmp = $this->userManager->searchDisplayName($search, $limit, $offset); + if ($this->shareeEnumerationPhone) { + $usersTmp = $this->userManager->searchKnownUsersByDisplayName($currentUserId, $search, $limit, $offset); + } else { + $usersTmp = $this->userManager->searchDisplayName($search, $limit, $offset); + } foreach ($usersTmp as $user) { if ($user->isEnabled()) { // Don't keep deactivated users $users[$user->getUID()] = $user; diff --git a/lib/private/User/Database.php b/lib/private/User/Database.php index 85e22d196e4..0534d38fd47 100644 --- a/lib/private/User/Database.php +++ b/lib/private/User/Database.php @@ -70,6 +70,7 @@ use OCP\User\Backend\ICreateUserBackend; use OCP\User\Backend\IGetDisplayNameBackend; use OCP\User\Backend\IGetHomeBackend; use OCP\User\Backend\IGetRealUIDBackend; +use OCP\User\Backend\ISearchKnownUsersBackend; use OCP\User\Backend\ISetDisplayNameBackend; use OCP\User\Backend\ISetPasswordBackend; @@ -84,6 +85,7 @@ class Database extends ABackend implements ICheckPasswordBackend, IGetHomeBackend, ICountUsersBackend, + ISearchKnownUsersBackend, IGetRealUIDBackend { /** @var CappedMemoryCache */ private $cache; @@ -277,7 +279,47 @@ class Database extends ABackend implements ->orWhere($query->expr()->iLike('displayname', $query->createPositionalParameter('%' . $this->dbConn->escapeLikeParameter($search) . '%'))) ->orWhere($query->expr()->iLike('configvalue', $query->createPositionalParameter('%' . $this->dbConn->escapeLikeParameter($search) . '%'))) ->orderBy($query->func()->lower('displayname'), 'ASC') - ->orderBy('uid_lower', 'ASC') + ->addOrderBy('uid_lower', 'ASC') + ->setMaxResults($limit) + ->setFirstResult($offset); + + $result = $query->execute(); + $displayNames = []; + while ($row = $result->fetch()) { + $displayNames[(string)$row['uid']] = (string)$row['displayname']; + } + + return $displayNames; + } + + /** + * @param string $searcher + * @param string $pattern + * @param int|null $limit + * @param int|null $offset + * @return array + * @since 21.0.1 + */ + public function searchKnownUsersByDisplayName(string $searcher, string $pattern, ?int $limit = null, ?int $offset = null): array { + $limit = $this->fixLimit($limit); + + $this->fixDI(); + + $query = $this->dbConn->getQueryBuilder(); + + $query->select('u.uid', 'u.displayname') + ->from($this->table, 'u') + ->leftJoin('u', 'known_users', 'k', $query->expr()->andX( + $query->expr()->eq('k.known_user', 'u.uid'), + $query->expr()->eq('k.known_to', $query->createNamedParameter($searcher)) + )) + ->where($query->expr()->eq('k.known_to', $query->createNamedParameter($searcher))) + ->andWhere($query->expr()->orX( + $query->expr()->iLike('u.uid', $query->createNamedParameter('%' . $this->dbConn->escapeLikeParameter($pattern) . '%')), + $query->expr()->iLike('u.displayname', $query->createNamedParameter('%' . $this->dbConn->escapeLikeParameter($pattern) . '%')) + )) + ->orderBy('u.displayname', 'ASC') + ->addOrderBy('u.uid_lower', 'ASC') ->setMaxResults($limit) ->setFirstResult($offset); diff --git a/lib/private/User/Manager.php b/lib/private/User/Manager.php index 036d2703d35..64aa5e1d22b 100644 --- a/lib/private/User/Manager.php +++ b/lib/private/User/Manager.php @@ -47,6 +47,7 @@ use OCP\IUserBackend; use OCP\IUserManager; use OCP\Support\Subscription\IRegistry; use OCP\User\Backend\IGetRealUIDBackend; +use OCP\User\Backend\ISearchKnownUsersBackend; use OCP\User\Events\BeforeUserCreatedEvent; use OCP\User\Events\UserCreatedEvent; use OCP\UserInterface; @@ -330,6 +331,41 @@ class Manager extends PublicEmitter implements IUserManager { } /** + * Search known users (from phonebook sync) by displayName + * + * @param string $searcher + * @param string $pattern + * @param int|null $limit + * @param int|null $offset + * @return IUser[] + */ + public function searchKnownUsersByDisplayName(string $searcher, string $pattern, ?int $limit = null, ?int $offset = null): array { + $users = []; + foreach ($this->backends as $backend) { + if ($backend instanceof ISearchKnownUsersBackend) { + $backendUsers = $backend->searchKnownUsersByDisplayName($searcher, $pattern, $limit, $offset); + } else { + // Better than nothing, but filtering after pagination can remove lots of results. + $backendUsers = $backend->getDisplayNames($pattern, $limit, $offset); + } + if (is_array($backendUsers)) { + foreach ($backendUsers as $uid => $displayName) { + $users[] = $this->getUserObject($uid, $backend); + } + } + } + + usort($users, function ($a, $b) { + /** + * @var IUser $a + * @var IUser $b + */ + return strcasecmp($a->getDisplayName(), $b->getDisplayName()); + }); + return $users; + } + + /** * @param string $uid * @param string $password * @throws \InvalidArgumentException |