diff options
Diffstat (limited to 'lib')
-rw-r--r-- | lib/private/Group/Database.php | 52 | ||||
-rw-r--r-- | lib/private/Group/Group.php | 17 | ||||
-rw-r--r-- | lib/private/User/LazyUser.php | 20 | ||||
-rw-r--r-- | lib/private/User/Manager.php | 29 | ||||
-rw-r--r-- | lib/public/Group/Backend/ABackend.php | 15 | ||||
-rw-r--r-- | lib/public/GroupInterface.php | 24 | ||||
-rw-r--r-- | lib/public/IGroup.php | 2 |
7 files changed, 126 insertions, 33 deletions
diff --git a/lib/private/Group/Database.php b/lib/private/Group/Database.php index 5f17477db77..bfc95c574e2 100644 --- a/lib/private/Group/Database.php +++ b/lib/private/Group/Database.php @@ -43,6 +43,9 @@ use OCP\Group\Backend\IRemoveFromGroupBackend; use OCP\Group\Backend\ISetDisplayNameBackend; use OCP\Group\Backend\INamedBackend; use OCP\IDBConnection; +use OCP\IUserManager; +use OC\User\LazyUser; +use OC\User\DisplayNameCache; /** * Class for group management in a SQL Database (e.g. MySQL, SQLite) @@ -376,6 +379,55 @@ class Database extends ABackend implements return $users; } + public function searchInGroup(string $gid, string $search = '', int $limit = -1, int $offset = 0): array { + $this->fixDI(); + + $query = $this->dbConn->getQueryBuilder(); + $query->select('g.uid', 'u.displayname'); + + $query->from('group_user', 'g') + ->where($query->expr()->eq('gid', $query->createNamedParameter($gid))) + ->orderBy('g.uid', 'ASC'); + + $query->leftJoin('g', 'users', 'u', $query->expr()->eq('g.uid', 'u.uid')) + + if ($search !== '') { + $query->leftJoin('u', 'preferences', 'p', $query->expr()->andX( + $query->expr()->eq('p.userid', 'u.uid'), + $query->expr()->eq('p.appid', $query->expr()->literal('settings')), + $query->expr()->eq('p.configkey', $query->expr()->literal('email')) + )) + // sqlite doesn't like re-using a single named parameter here + ->andWhere( + $query->expr()->orX( + $query->expr()->ilike('g.uid', $query->createNamedParameter('%' . $this->dbConn->escapeLikeParameter($search) . '%')), + $query->expr()->ilike('u.displayname', $query->createNamedParameter('%' . $this->dbConn->escapeLikeParameter($search) . '%')), + $query->expr()->ilike('p.configvalue', $query->createNamedParameter('%' . $this->dbConn->escapeLikeParameter($search) . '%')) + ) + ) + ->orderBy('u.uid_lower', 'ASC'); + } + + if ($limit !== -1) { + $query->setMaxResults($limit); + } + if ($offset !== 0) { + $query->setFirstResult($offset); + } + + $result = $query->executeQuery(); + + $users = []; + $userManager = \OCP\Server::get(IUserManager::class); + $displayNameCache = \OCP\Server::get(DisplayNameCache::class); + while ($row = $result->fetch()) { + $users[$row['uid']] = new LazyUser($row['uid'], $displayNameCache, $userManager, $row['displayname'] ?? null); + } + $result->closeCursor(); + + return $users; + } + /** * get the number of all users matching the search string in a group * @param string $gid diff --git a/lib/private/Group/Group.php b/lib/private/Group/Group.php index cca179bfe19..b2903bcdb26 100644 --- a/lib/private/Group/Group.php +++ b/lib/private/Group/Group.php @@ -242,18 +242,13 @@ class Group implements IGroup { } /** - * search for users in the group by userid - * - * @param string $search - * @param int $limit - * @param int $offset - * @return \OC\User\User[] + * Search for users in the group by userid or display name + * @return IUser[] */ - public function searchUsers($search, $limit = null, $offset = null) { + public function searchUsers(string $search, ?int $limit = null, ?int $offset = null): array { $users = []; foreach ($this->backends as $backend) { - $userIds = $backend->usersInGroup($this->gid, $search, $limit, $offset); - $users += $this->getVerifiedUsers($userIds); + $users = array_merge($users, $backend->searchInGroup($this->gid, $search, $limit ?? -1, $offset ?? 0)); if (!is_null($limit) and $limit <= 0) { return $users; } @@ -309,12 +304,12 @@ class Group implements IGroup { * @param int $limit * @param int $offset * @return \OC\User\User[] + * @deprecated 25.0.0 Use searchUsers instead (same implementation) */ public function searchDisplayName($search, $limit = null, $offset = null) { $users = []; foreach ($this->backends as $backend) { - $userIds = $backend->usersInGroup($this->gid, $search, $limit, $offset); - $users = $this->getVerifiedUsers($userIds); + $users = array_merge($users, $backend->searchInGroup($this->gid, $search, $limit ?? -1, $offset ?? 0)); if (!is_null($limit) and $limit <= 0) { return array_values($users); } diff --git a/lib/private/User/LazyUser.php b/lib/private/User/LazyUser.php index 096578b8f37..c36ff86eff4 100644 --- a/lib/private/User/LazyUser.php +++ b/lib/private/User/LazyUser.php @@ -30,16 +30,26 @@ use OCP\UserInterface; class LazyUser implements IUser { private ?IUser $user = null; private string $uid; + private ?string $displayName; private IUserManager $userManager; + private ?UserInterface $backend; - public function __construct(string $uid, IUserManager $userManager) { + public function __construct(string $uid, IUserManager $userManager, ?string $displayName = null, ?UserInterface $backend = null) { $this->uid = $uid; $this->userManager = $userManager; + $this->displayName = $displayName; + $this->backend = $backend; } private function getUser(): IUser { if ($this->user === null) { - $this->user = $this->userManager->get($this->uid); + if ($this->backend) { + /** @var \OC\User\Manager $manager */ + $manager = $this->userManager; + $this->user = $manager->getUserObject($this->uid, $this->backend); + } else { + $this->user = $this->userManager->get($this->uid); + } } /** @var IUser */ $user = $this->user; @@ -51,7 +61,11 @@ class LazyUser implements IUser { } public function getDisplayName() { - return $this->userManager->getDisplayName($this->uid) ?? $this->uid; + if ($this->displayName) { + return $this->displayName; + } + + return $this->userManager->getDisplayName($this->uid); } public function setDisplayName($displayName) { diff --git a/lib/private/User/Manager.php b/lib/private/User/Manager.php index 859ebd2a604..c3275934a5a 100644 --- a/lib/private/User/Manager.php +++ b/lib/private/User/Manager.php @@ -202,7 +202,7 @@ class Manager extends PublicEmitter implements IUserManager { * @param bool $cacheUser If false the newly created user object will not be cached * @return \OC\User\User */ - protected function getUserObject($uid, $backend, $cacheUser = true) { + public function getUserObject($uid, $backend, $cacheUser = true) { if ($backend instanceof IGetRealUIDBackend) { $uid = $backend->getRealUID($uid); } @@ -293,58 +293,53 @@ class Manager extends PublicEmitter implements IUserManager { } /** - * search by user id + * Search by user id * * @param string $pattern * @param int $limit * @param int $offset - * @return \OC\User\User[] + * @return IUser[] + * @deprecated since 25.0.0, use searchDisplayName instead */ public function search($pattern, $limit = null, $offset = null) { $users = []; + $displayNameCache = \OCP\Server::get(DisplayNameCache::class); foreach ($this->backends as $backend) { $backendUsers = $backend->getUsers($pattern, $limit, $offset); if (is_array($backendUsers)) { foreach ($backendUsers as $uid) { - $users[$uid] = $this->getUserObject($uid, $backend); + $users[$uid] = new LazyUser($uid, $displayNameCache, $this, null, $backend); } } } - uasort($users, function ($a, $b) { - /** - * @var \OC\User\User $a - * @var \OC\User\User $b - */ + uasort($users, function (IUser $a, IUser $b) { return strcasecmp($a->getUID(), $b->getUID()); }); return $users; } /** - * search by displayName + * Search by displayName * * @param string $pattern * @param int $limit * @param int $offset - * @return \OC\User\User[] + * @return IUser[] */ public function searchDisplayName($pattern, $limit = null, $offset = null) { $users = []; + $displayNameCache = \OCP\Server::get(DisplayNameCache::class); foreach ($this->backends as $backend) { $backendUsers = $backend->getDisplayNames($pattern, $limit, $offset); if (is_array($backendUsers)) { foreach ($backendUsers as $uid => $displayName) { - $users[] = $this->getUserObject($uid, $backend); + $users[] = new LazyUser($uid, $displayNameCache, $this, $displayName, $backend); } } } - usort($users, function ($a, $b) { - /** - * @var \OC\User\User $a - * @var \OC\User\User $b - */ + usort($users, function (IUser $a, IUser $b) { return strcasecmp($a->getDisplayName(), $b->getDisplayName()); }); return $users; diff --git a/lib/public/Group/Backend/ABackend.php b/lib/public/Group/Backend/ABackend.php index 7f5cf732335..e76285dfda9 100644 --- a/lib/public/Group/Backend/ABackend.php +++ b/lib/public/Group/Backend/ABackend.php @@ -26,6 +26,10 @@ declare(strict_types=1); namespace OCP\Group\Backend; use OCP\GroupInterface; +use OCP\IUserManager; +use OCP\Server; +use OC\User\LazyUser; +use OC\User\DisplayNameCache; /** * @since 14.0.0 @@ -65,4 +69,15 @@ abstract class ABackend implements GroupInterface { return (bool)($actions & $implements); } + + public function searchInGroup(string $gid, string $search = '', int $limit = -1, int $offset = 0): array { + // Default implementation for compatibility reasons + $displayNameCache = Server::get(DisplayNameCache::class); + $userManager = Server::get(IUserManager::class); + $users = []; + foreach ($this->usersInGroup($gid, $search, $limit, $offset) as $userId) { + $users[$userId] = new LazyUser($userId, $displayNameCache, $userManager); + } + return $users; + } } diff --git a/lib/public/GroupInterface.php b/lib/public/GroupInterface.php index b7c07136126..07fd5cb50c4 100644 --- a/lib/public/GroupInterface.php +++ b/lib/public/GroupInterface.php @@ -106,13 +106,35 @@ interface GroupInterface { public function groupExists($gid); /** - * get a list of all users in a group + * @brief Get a list of user ids in a group matching the given search parameters. + * * @param string $gid * @param string $search * @param int $limit * @param int $offset * @return array an array of user ids * @since 4.5.0 + * @deprecated 25.0.0 Use searchInGroup instead, for performance reasons */ public function usersInGroup($gid, $search = '', $limit = -1, $offset = 0); + + /** + * @brief Get a list of users matching the given search parameters. + * + * Implementations of this method should return lazy evaluated user objects and + * preload if possible the display name. + * + * <code> + * $users = $groupBackend->searchInGroup('admin', 'John', 10, 0); + * </code> + * + * @param string $gid The group id of the user we want to search + * @param string $search The part of the display name or user id of the users we + * want to search. This can be empty to get all the users. + * @param int $limit The limit of results + * @param int $offset The offset of the results + * @return IUser[] + * @since 25.0.0 + */ + public function searchInGroup(string $gid, string $search = '', int $limit = -1, int $offset = 0): array; } diff --git a/lib/public/IGroup.php b/lib/public/IGroup.php index ba13359c472..ec26cc55b69 100644 --- a/lib/public/IGroup.php +++ b/lib/public/IGroup.php @@ -99,7 +99,7 @@ interface IGroup { * @return \OCP\IUser[] * @since 8.0.0 */ - public function searchUsers($search, $limit = null, $offset = null); + public function searchUsers(string $search, ?int $limit = null, ?int $offset = null): array; /** * returns the number of users matching the search string |