From 7da80d207a2d897e7fcb8cacd4913a91004dc699 Mon Sep 17 00:00:00 2001 From: Claus-Justus Heine Date: Tue, 22 Aug 2023 12:35:26 +0200 Subject: [PATCH] Implement ISearchableGroupBackend Signed-off-by: Claus-Justus Heine --- lib/Backend/GroupBackend.php | 61 +++++++++++++++++++++++++++--- lib/Constant/Query.php | 1 + lib/Query/DataQuery.php | 21 ++++++++++ lib/Query/QueryProvider.php | 21 +++++++--- lib/Repository/GroupRepository.php | 23 +++++++++++ 5 files changed, 115 insertions(+), 12 deletions(-) diff --git a/lib/Backend/GroupBackend.php b/lib/Backend/GroupBackend.php index c41a40d..e48a2a5 100644 --- a/lib/Backend/GroupBackend.php +++ b/lib/Backend/GroupBackend.php @@ -31,7 +31,11 @@ use OCP\Group\Backend\ABackend; use OCP\Group\Backend\ICountUsersBackend; use OCP\Group\Backend\IGroupDetailsBackend; use OCP\Group\Backend\IIsAdminBackend; +use OCP\Group\Backend\ISearchableGroupBackend; use OCP\ILogger; +use OCP\IUserManager; + +use OC\User\LazyUser; /** * The SQL group backend manager. @@ -41,7 +45,8 @@ use OCP\ILogger; final class GroupBackend extends ABackend implements ICountUsersBackend, IGroupDetailsBackend, - IIsAdminBackend + IIsAdminBackend, + ISearchableGroupBackend { const USER_SQL_GID = "user_sql"; @@ -354,16 +359,16 @@ final class GroupBackend extends ABackend implements ["app" => $this->appName] ); - $cacheKey = self::class . "group_users_" . $gid . "_" . $search . "_" + $cacheKey = self::class . "group_uids_" . $gid . "_" . $search . "_" . $limit . "_" . $offset; - $users = $this->cache->get($cacheKey); + $uids = $this->cache->get($cacheKey); - if (!is_null($users)) { + if (!is_null($uids)) { $this->logger->debug( "Returning from cache usersInGroup($gid, $search, $limit, $offset): count(" - . count($users) . ")", ["app" => $this->appName] + . count($uids) . ")", ["app" => $this->appName] ); - return $users; + return $uids; } $uids = $this->groupRepository->findAllUidsBySearchTerm( @@ -383,6 +388,50 @@ final class GroupBackend extends ABackend implements return $uids; } + /** + * @inheritdoc + */ + public function searchInGroup(string $gid, string $search = '', int $limit = -1, int $offset = 0): array + { + $this->logger->debug( + "Entering searchInGroup($gid, $search, $limit, $offset)", + ["app" => $this->appName] + ); + + $cacheKey = self::class . "group_users_" . $gid . "_" . $search . "_" + . $limit . "_" . $offset; + $names = $this->cache->get($cacheKey); + + if ($names === null) { + $names = $this->groupRepository->findAllUsersBySearchTerm( + $this->substituteGid($gid), "%" . $search . "%", $limit, $offset + ); + + if ($names === false) { + return []; + } + + $this->cache->set($cacheKey, $names); + $this->logger->debug( + "Using from DB searchInGroup($gid, $search, $limit, $offset): count(" + . count($names) . ")", ["app" => $this->appName] + ); + } else { + $this->logger->debug( + "Using from cache searchInGroup($gid, $search, $limit, $offset): count(" + . count($names) . ")", ["app" => $this->appName] + ); + } + + $users = []; + $userManager = \OCP\Server::get(IUserManager::class); + foreach ($names as $uid => $name) { + $users[$uid] = new LazyUser($uid, $userManager, $name); + } + + return $users; + } + /** * @inheritdoc */ diff --git a/lib/Constant/Query.php b/lib/Constant/Query.php index 68ceff8..373e2ca 100644 --- a/lib/Constant/Query.php +++ b/lib/Constant/Query.php @@ -32,6 +32,7 @@ final class Query const COUNT_GROUPS = "count_groups"; const COUNT_USERS = "count_users"; const FIND_GROUP = "find_group"; + const FIND_GROUP_UIDS = "find_group_uids"; const FIND_GROUP_USERS = "find_group_users"; const FIND_GROUPS = "find_groups"; const FIND_USER_BY_UID = "find_user_by_uid"; diff --git a/lib/Query/DataQuery.php b/lib/Query/DataQuery.php index 8feefd1..1a7e2ae 100644 --- a/lib/Query/DataQuery.php +++ b/lib/Query/DataQuery.php @@ -223,6 +223,27 @@ class DataQuery return $result->fetchFirstColumn(); } + /** + * Fetch values from all columns which the given query returns. + * + * @param string $queryName The query to execute. + * @param array $params The query parameters to bind. + * @param int $limit Results limit. Defaults to -1 (no limit). + * @param int $offset Results offset. Defaults to 0. + * + * @return array|bool Queried column or FALSE on failure. + */ + public function queryColumns( + $queryName, $params = [], $limit = -1, $offset = 0 + ) { + $result = $this->execQuery($queryName, $params, $limit, $offset); + if ($result === false) { + return false; + } + + return $result->fetchAll(); + } + /** * Fetch entity returned by the given query. * diff --git a/lib/Query/QueryProvider.php b/lib/Query/QueryProvider.php index 61278a3..70323c8 100644 --- a/lib/Query/QueryProvider.php +++ b/lib/Query/QueryProvider.php @@ -154,14 +154,23 @@ class QueryProvider implements \ArrayAccess "FROM $group g " . "WHERE g.$gGID = :$gidParam", - Query::FIND_GROUP_USERS => - "SELECT DISTINCT ug.$ugUID AS uid " . - "FROM $userGroup ug " . - "LEFT JOIN $user u ON u.$uUID = ug.$ugUID " . + Query::FIND_GROUP_UIDS => + "SELECT DISTINCT u.$uUID AS uid " . + "FROM $user u " . + "LEFT JOIN $userGroup ug ON u.$uUID = ug.$ugUID " . "WHERE ug.$ugGID LIKE :$gidParam " . - "AND ug.$ugUID LIKE :$searchParam " . + "AND u.$uUID LIKE :$searchParam " . (empty($uDisabled) ? "" : "AND NOT u.$uDisabled ") . - "ORDER BY ug.$ugUID", + "ORDER BY u.$uUID", + + Query::FIND_GROUP_USERS => + "SELECT DISTINCT u.$uUID AS uid, u.$uName AS name " . + "FROM $user u " . + "LEFT JOIN $userGroup ug ON u.$uUID = ug.$ugUID " . + "WHERE ug.$ugGID LIKE :$gidParam " . + "AND u.$uUID LIKE :$searchParam " . + (empty($uDisabled) ? "" : "AND NOT u.$uDisabled ") . + "ORDER BY u.$uUID", Query::FIND_GROUPS => "SELECT $groupColumns " . diff --git a/lib/Repository/GroupRepository.php b/lib/Repository/GroupRepository.php index f0203c3..1ac8470 100644 --- a/lib/Repository/GroupRepository.php +++ b/lib/Repository/GroupRepository.php @@ -92,10 +92,33 @@ class GroupRepository $gid, $search = "", $limit = -1, $offset = 0 ) { return $this->dataQuery->queryColumn( + Query::FIND_GROUP_UIDS, + [Query::GID_PARAM => $gid, Query::SEARCH_PARAM => $search], $limit, + $offset + ); + } + + /** + * Get a list of all user IDs and their display-name belonging to the group. + * + * @param string $gid The group ID. + * @param string $search The UID search term. Defaults to "" (empty string). + * @param int $limit (optional) Results limit. + * Defaults to -1 (no limit). + * @param int $offset (optional) Results offset. Defaults to 0. + * + * @return array Array of display-names indexed by UIDs belonging to the group + * or FALSE on failure. + */ + public function findAllUsersBySearchTerm( + $gid, $search = "", $limit = -1, $offset = 0 + ) { + $data = $this->dataQuery->queryColumns( Query::FIND_GROUP_USERS, [Query::GID_PARAM => $gid, Query::SEARCH_PARAM => $search], $limit, $offset ); + return array_column($data, QUERY::NAME_PARAM, Query::UID_PARAM); } /**