diff --git a/src/main/java/org/qortal/api/resource/GroupsResource.java b/src/main/java/org/qortal/api/resource/GroupsResource.java index 7c3054e1c..24a1e1ef7 100644 --- a/src/main/java/org/qortal/api/resource/GroupsResource.java +++ b/src/main/java/org/qortal/api/resource/GroupsResource.java @@ -165,6 +165,45 @@ public GroupData getGroupData(@PathParam("groupid") int groupId) { } } + @GET + @Path("/search") + @Operation( + summary = "Search group name and description fields", + responses = { + @ApiResponse( + description = "group info", + content = @Content( + mediaType = MediaType.APPLICATION_JSON, + array = @ArraySchema(schema = @Schema(implementation = GroupData.class)) + ) + ) + } + ) + @ApiErrors({ApiError.REPOSITORY_ISSUE}) + public List searchGroups(@Parameter( + description = "Query (searches name and description fields)" + ) @QueryParam("query") String query, @Parameter( + ref = "limit" + ) @QueryParam("limit") Integer limit, @Parameter( + ref = "offset" + ) @QueryParam("offset") Integer offset, @Parameter( + ref = "reverse" + ) @QueryParam("reverse") Boolean reverse) { + try (final Repository repository = RepositoryManager.getRepository()) { + List searchResults = repository.getGroupRepository().searchGroups(query, limit, offset, reverse); + searchResults.forEach(result -> { + try { + result.memberCount = repository.getGroupRepository().countGroupMembers(result.getGroupId()); + } catch (DataException e) { + // Exclude memberCount for this group + } + }); + return searchResults; + } catch (DataException e) { + throw ApiExceptionFactory.INSTANCE.createException(request, ApiError.REPOSITORY_ISSUE, e); + } + } + @GET @Path("/members/{groupid}") @Operation( diff --git a/src/main/java/org/qortal/repository/GroupRepository.java b/src/main/java/org/qortal/repository/GroupRepository.java index 49427b02b..7dac417a6 100644 --- a/src/main/java/org/qortal/repository/GroupRepository.java +++ b/src/main/java/org/qortal/repository/GroupRepository.java @@ -36,6 +36,8 @@ public default List getGroupsWithMember(String member) throws DataExc return getGroupsWithMember(member, null, null, null); } + public List searchGroups(String query, Integer limit, Integer offset, Boolean reverse) throws DataException; + public void save(GroupData groupData) throws DataException; public void delete(int groupId) throws DataException; diff --git a/src/main/java/org/qortal/repository/hsqldb/HSQLDBGroupRepository.java b/src/main/java/org/qortal/repository/hsqldb/HSQLDBGroupRepository.java index 9c7521fc9..2d03fd65f 100644 --- a/src/main/java/org/qortal/repository/hsqldb/HSQLDBGroupRepository.java +++ b/src/main/java/org/qortal/repository/hsqldb/HSQLDBGroupRepository.java @@ -287,6 +287,69 @@ public List getGroupsWithMember(String member, Integer limit, Integer } } + @Override + public List searchGroups(String query, Integer limit, Integer offset, Boolean reverse) throws DataException { + StringBuilder sql = new StringBuilder(512); + List bindParams = new ArrayList<>(); + + sql.append("SELECT group_id, owner, group_name, description, created_when, updated_when, reference, is_open, " + + "approval_threshold, min_block_delay, max_block_delay, creation_group_id, reduced_group_name " + + "FROM Groups"); + + // Handle general query matches + if (query != null) { + String queryWildcard = String.format("%%%s%%", query.toLowerCase()); + sql.append(" WHERE (LCASE(group_name) LIKE ? OR LCASE(description) LIKE ?)"); + bindParams.add(queryWildcard); bindParams.add(queryWildcard); + } + + sql.append(" ORDER BY group_name"); + + if (reverse != null && reverse) + sql.append(" DESC"); + + HSQLDBRepository.limitOffsetSql(sql, limit, offset); + + List groups = new ArrayList<>(); + + try (ResultSet resultSet = this.repository.checkedExecute(sql.toString(), bindParams.toArray())) { + if (resultSet == null) + return groups; + + do { + int groupId = resultSet.getInt(1); + String owner = resultSet.getString(2); + String groupName = resultSet.getString(3); + String description = resultSet.getString(4); + long created = resultSet.getLong(5); + + // Special handling for possibly-NULL "updated" column + Long updated = resultSet.getLong(6); + if (updated == 0 && resultSet.wasNull()) + updated = null; + + byte[] reference = resultSet.getBytes(7); + boolean isOpen = resultSet.getBoolean(8); + + ApprovalThreshold approvalThreshold = ApprovalThreshold.valueOf(resultSet.getInt(9)); + + int minBlockDelay = resultSet.getInt(10); + int maxBlockDelay = resultSet.getInt(11); + + int creationGroupId = resultSet.getInt(12); + String reducedGroupName = resultSet.getString(13); + + groups.add(new GroupData(groupId, owner, groupName, description, created, updated, isOpen, + approvalThreshold, minBlockDelay, maxBlockDelay, + reference, creationGroupId, reducedGroupName)); + } while (resultSet.next()); + + return groups; + } catch (SQLException e) { + throw new DataException("Unable to fetch groups from repository", e); + } + } + @Override public void save(GroupData groupData) throws DataException { HSQLDBSaver saveHelper = new HSQLDBSaver("Groups");