We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Assigning group members: memberlist batch navigation is broken.
## groupmembers listing batch and `showAll` link is broken

### What I did:

Assign members to a group:

- click on "show all" in the user filter.
- if you have lots of users the list is batched
- click on the next batch page

### What I expect to happen:

the next user batch list is shown

### What actually happened:

the user list is empty

### What version of Plone/ Addons I am using:

Plone 6.0.2


### Additional

The "toggle all" checkboxes do not work. This can be solved with `pat-checklist` ...

--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `Products/CMFPlone/controlpanel/browser/usergroups_groupmembership.py`
Content:
```
1 from Products.CMFCore.utils import getToolByName
2 from Products.CMFPlone import PloneMessageFactory as _
3 from Products.CMFPlone.controlpanel.browser.usergroups import (
4     UsersGroupsControlPanelView,
5 )
6 from Products.CMFPlone.utils import normalizeString
7 from zExceptions import Forbidden
8 
9 
10 class GroupMembershipControlPanel(UsersGroupsControlPanelView):
11 
12     def update(self):
13         self.groupname = getattr(self.request, 'groupname')
14         self.gtool = getToolByName(self, 'portal_groups')
15         self.mtool = getToolByName(self, 'portal_membership')
16         self.group = self.gtool.getGroupById(self.groupname)
17         if self.group is None:
18             return
19 
20         self.grouptitle = self.group.getGroupTitleOrName() or self.groupname
21 
22         self.request.set('grouproles', self.group.getRoles()
23                          if self.group else [])
24         self.canAddUsers = True
25         if 'Manager' in self.request.get('grouproles') and not self.is_zope_manager:
26             self.canAddUsers = False
27 
28         self.groupquery = self.makeQuery(groupname=self.groupname)
29         self.groupkeyquery = self.makeQuery(key=self.groupname)
30 
31         form = self.request.form
32         submitted = form.get('form.submitted', False)
33 
34         self.searchResults = []
35         self.searchString = ''
36         self.newSearch = False
37 
38         if submitted:
39             # add/delete before we search so we don't show stale results
40             toAdd = form.get('add', [])
41             if toAdd:
42                 if not self.canAddUsers:
43                     raise Forbidden
44 
45                 for u in toAdd:
46                     self.gtool.addPrincipalToGroup(
47                         u, self.groupname, self.request)
48                 self.context.plone_utils.addPortalMessage(_('Changes made.'))
49 
50             toDelete = form.get('delete', [])
51             if toDelete:
52                 for u in toDelete:
53                     self.gtool.removePrincipalFromGroup(
54                         u, self.groupname, self.request)
55                 self.context.plone_utils.addPortalMessage(_('Changes made.'))
56 
57             search = form.get('form.button.Search', None) is not None
58             edit = form.get('form.button.Edit', None) is not None and toDelete
59             add = form.get('form.button.Add', None) is not None and toAdd
60             findAll = form.get('form.button.FindAll', None) is not None and \
61                 not self.many_users
62             # The search string should be cleared when one of the
63             # non-search buttons has been clicked.
64             if findAll or edit or add:
65                 form['searchstring'] = ''
66             self.searchString = form.get('searchstring', '')
67             if findAll or bool(self.searchString):
68                 self.searchResults = self.getPotentialMembers(
69                     self.searchString)
70 
71             if search or findAll:
72                 self.newSearch = True
73 
74         self.groupMembers = self.getMembers()
75 
76     def __call__(self):
77         self.update()
78         return self.index()
79 
80     def isGroup(self, itemName):
81         return self.gtool.isGroup(itemName)
82 
83     def getMembers(self):
84         searchResults = self.gtool.getGroupMembers(self.groupname)
85 
86         groupResults = []
87         userResults = []
88         for principal_id in searchResults:
89             principal = self.gtool.getGroupById(principal_id)
90             if principal is not None:
91                 groupResults.append(principal)
92                 continue
93             principal = self.mtool.getMemberById(principal_id)
94             if principal is not None:
95                 userResults.append(principal)
96 
97         groupResults.sort(key=lambda x: normalizeString(x.getGroupTitleOrName()))
98         userResults.sort(key=lambda x: normalizeString(x.getProperty('fullname') or ''))
99 
100         return groupResults + userResults
101 
102     def getPotentialMembers(self, searchString):
103         ignoredUsersGroups = [
104             x.id for x in self.getMembers() + [self.group, ] if x is not None]
105         return self.membershipSearch(searchString, ignore=ignoredUsersGroups)
106
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/Products/CMFPlone/controlpanel/browser/usergroups_groupmembership.py b/Products/CMFPlone/controlpanel/browser/usergroups_groupmembership.py
--- a/Products/CMFPlone/controlpanel/browser/usergroups_groupmembership.py
+++ b/Products/CMFPlone/controlpanel/browser/usergroups_groupmembership.py
@@ -57,14 +57,21 @@
             search = form.get('form.button.Search', None) is not None
             edit = form.get('form.button.Edit', None) is not None and toDelete
             add = form.get('form.button.Add', None) is not None and toAdd
-            findAll = form.get('form.button.FindAll', None) is not None and \
-                not self.many_users
+            isBatched = form.get("b_start", None) is not None
+            findAll = (
+                form.get('form.button.FindAll', None) is not None
+                and not self.many_users
+            )
+            unbatchedAll = (
+                form.get("showAll", "") == "y"
+                and not self.many_users
+            )
             # The search string should be cleared when one of the
             # non-search buttons has been clicked.
-            if findAll or edit or add:
+            if findAll or unbatchedAll or edit or add:
                 form['searchstring'] = ''
             self.searchString = form.get('searchstring', '')
-            if findAll or bool(self.searchString):
+            if findAll or isBatched or unbatchedAll or bool(self.searchString):
                 self.searchResults = self.getPotentialMembers(
                     self.searchString)

{"golden_diff": "diff --git a/Products/CMFPlone/controlpanel/browser/usergroups_groupmembership.py b/Products/CMFPlone/controlpanel/browser/usergroups_groupmembership.py\n--- a/Products/CMFPlone/controlpanel/browser/usergroups_groupmembership.py\n+++ b/Products/CMFPlone/controlpanel/browser/usergroups_groupmembership.py\n@@ -57,14 +57,21 @@\n             search = form.get('form.button.Search', None) is not None\n             edit = form.get('form.button.Edit', None) is not None and toDelete\n             add = form.get('form.button.Add', None) is not None and toAdd\n-            findAll = form.get('form.button.FindAll', None) is not None and \\\n-                not self.many_users\n+            isBatched = form.get(\"b_start\", None) is not None\n+            findAll = (\n+                form.get('form.button.FindAll', None) is not None\n+                and not self.many_users\n+            )\n+            unbatchedAll = (\n+                form.get(\"showAll\", \"\") == \"y\"\n+                and not self.many_users\n+            )\n             # The search string should be cleared when one of the\n             # non-search buttons has been clicked.\n-            if findAll or edit or add:\n+            if findAll or unbatchedAll or edit or add:\n                 form['searchstring'] = ''\n             self.searchString = form.get('searchstring', '')\n-            if findAll or bool(self.searchString):\n+            if findAll or isBatched or unbatchedAll or bool(self.searchString):\n                 self.searchResults = self.getPotentialMembers(\n                     self.searchString)\n", "issue": "Assigning group members: memberlist batch navigation is broken.\n## groupmembers listing batch and `showAll` link is broken\r\n\r\n### What I did:\r\n\r\nAssign members to a group:\r\n\r\n- click on \"show all\" in the user filter.\r\n- if you have lots of users the list is batched\r\n- click on the next batch page\r\n\r\n### What I expect to happen:\r\n\r\nthe next user batch list is shown\r\n\r\n### What actually happened:\r\n\r\nthe user list is empty\r\n\r\n### What version of Plone/ Addons I am using:\r\n\r\nPlone 6.0.2\r\n\r\n\r\n### Additional\r\n\r\nThe \"toggle all\" checkboxes do not work. This can be solved with `pat-checklist` ...\n", "before_files": [{"content": "from Products.CMFCore.utils import getToolByName\nfrom Products.CMFPlone import PloneMessageFactory as _\nfrom Products.CMFPlone.controlpanel.browser.usergroups import (\n    UsersGroupsControlPanelView,\n)\nfrom Products.CMFPlone.utils import normalizeString\nfrom zExceptions import Forbidden\n\n\nclass GroupMembershipControlPanel(UsersGroupsControlPanelView):\n\n    def update(self):\n        self.groupname = getattr(self.request, 'groupname')\n        self.gtool = getToolByName(self, 'portal_groups')\n        self.mtool = getToolByName(self, 'portal_membership')\n        self.group = self.gtool.getGroupById(self.groupname)\n        if self.group is None:\n            return\n\n        self.grouptitle = self.group.getGroupTitleOrName() or self.groupname\n\n        self.request.set('grouproles', self.group.getRoles()\n                         if self.group else [])\n        self.canAddUsers = True\n        if 'Manager' in self.request.get('grouproles') and not self.is_zope_manager:\n            self.canAddUsers = False\n\n        self.groupquery = self.makeQuery(groupname=self.groupname)\n        self.groupkeyquery = self.makeQuery(key=self.groupname)\n\n        form = self.request.form\n        submitted = form.get('form.submitted', False)\n\n        self.searchResults = []\n        self.searchString = ''\n        self.newSearch = False\n\n        if submitted:\n            # add/delete before we search so we don't show stale results\n            toAdd = form.get('add', [])\n            if toAdd:\n                if not self.canAddUsers:\n                    raise Forbidden\n\n                for u in toAdd:\n                    self.gtool.addPrincipalToGroup(\n                        u, self.groupname, self.request)\n                self.context.plone_utils.addPortalMessage(_('Changes made.'))\n\n            toDelete = form.get('delete', [])\n            if toDelete:\n                for u in toDelete:\n                    self.gtool.removePrincipalFromGroup(\n                        u, self.groupname, self.request)\n                self.context.plone_utils.addPortalMessage(_('Changes made.'))\n\n            search = form.get('form.button.Search', None) is not None\n            edit = form.get('form.button.Edit', None) is not None and toDelete\n            add = form.get('form.button.Add', None) is not None and toAdd\n            findAll = form.get('form.button.FindAll', None) is not None and \\\n                not self.many_users\n            # The search string should be cleared when one of the\n            # non-search buttons has been clicked.\n            if findAll or edit or add:\n                form['searchstring'] = ''\n            self.searchString = form.get('searchstring', '')\n            if findAll or bool(self.searchString):\n                self.searchResults = self.getPotentialMembers(\n                    self.searchString)\n\n            if search or findAll:\n                self.newSearch = True\n\n        self.groupMembers = self.getMembers()\n\n    def __call__(self):\n        self.update()\n        return self.index()\n\n    def isGroup(self, itemName):\n        return self.gtool.isGroup(itemName)\n\n    def getMembers(self):\n        searchResults = self.gtool.getGroupMembers(self.groupname)\n\n        groupResults = []\n        userResults = []\n        for principal_id in searchResults:\n            principal = self.gtool.getGroupById(principal_id)\n            if principal is not None:\n                groupResults.append(principal)\n                continue\n            principal = self.mtool.getMemberById(principal_id)\n            if principal is not None:\n                userResults.append(principal)\n\n        groupResults.sort(key=lambda x: normalizeString(x.getGroupTitleOrName()))\n        userResults.sort(key=lambda x: normalizeString(x.getProperty('fullname') or ''))\n\n        return groupResults + userResults\n\n    def getPotentialMembers(self, searchString):\n        ignoredUsersGroups = [\n            x.id for x in self.getMembers() + [self.group, ] if x is not None]\n        return self.membershipSearch(searchString, ignore=ignoredUsersGroups)\n", "path": "Products/CMFPlone/controlpanel/browser/usergroups_groupmembership.py"}], "after_files": [{"content": "from Products.CMFCore.utils import getToolByName\nfrom Products.CMFPlone import PloneMessageFactory as _\nfrom Products.CMFPlone.controlpanel.browser.usergroups import (\n    UsersGroupsControlPanelView,\n)\nfrom Products.CMFPlone.utils import normalizeString\nfrom zExceptions import Forbidden\n\n\nclass GroupMembershipControlPanel(UsersGroupsControlPanelView):\n\n    def update(self):\n        self.groupname = getattr(self.request, 'groupname')\n        self.gtool = getToolByName(self, 'portal_groups')\n        self.mtool = getToolByName(self, 'portal_membership')\n        self.group = self.gtool.getGroupById(self.groupname)\n        if self.group is None:\n            return\n\n        self.grouptitle = self.group.getGroupTitleOrName() or self.groupname\n\n        self.request.set('grouproles', self.group.getRoles()\n                         if self.group else [])\n        self.canAddUsers = True\n        if 'Manager' in self.request.get('grouproles') and not self.is_zope_manager:\n            self.canAddUsers = False\n\n        self.groupquery = self.makeQuery(groupname=self.groupname)\n        self.groupkeyquery = self.makeQuery(key=self.groupname)\n\n        form = self.request.form\n        submitted = form.get('form.submitted', False)\n\n        self.searchResults = []\n        self.searchString = ''\n        self.newSearch = False\n\n        if submitted:\n            # add/delete before we search so we don't show stale results\n            toAdd = form.get('add', [])\n            if toAdd:\n                if not self.canAddUsers:\n                    raise Forbidden\n\n                for u in toAdd:\n                    self.gtool.addPrincipalToGroup(\n                        u, self.groupname, self.request)\n                self.context.plone_utils.addPortalMessage(_('Changes made.'))\n\n            toDelete = form.get('delete', [])\n            if toDelete:\n                for u in toDelete:\n                    self.gtool.removePrincipalFromGroup(\n                        u, self.groupname, self.request)\n                self.context.plone_utils.addPortalMessage(_('Changes made.'))\n\n            search = form.get('form.button.Search', None) is not None\n            edit = form.get('form.button.Edit', None) is not None and toDelete\n            add = form.get('form.button.Add', None) is not None and toAdd\n            isBatched = form.get(\"b_start\", None) is not None\n            findAll = (\n                form.get('form.button.FindAll', None) is not None\n                and not self.many_users\n            )\n            unbatchedAll = (\n                form.get(\"showAll\", \"\") == \"y\"\n                and not self.many_users\n            )\n            # The search string should be cleared when one of the\n            # non-search buttons has been clicked.\n            if findAll or unbatchedAll or edit or add:\n                form['searchstring'] = ''\n            self.searchString = form.get('searchstring', '')\n            if findAll or isBatched or unbatchedAll or bool(self.searchString):\n                self.searchResults = self.getPotentialMembers(\n                    self.searchString)\n\n            if search or findAll:\n                self.newSearch = True\n\n        self.groupMembers = self.getMembers()\n\n    def __call__(self):\n        self.update()\n        return self.index()\n\n    def isGroup(self, itemName):\n        return self.gtool.isGroup(itemName)\n\n    def getMembers(self):\n        searchResults = self.gtool.getGroupMembers(self.groupname)\n\n        groupResults = []\n        userResults = []\n        for principal_id in searchResults:\n            principal = self.gtool.getGroupById(principal_id)\n            if principal is not None:\n                groupResults.append(principal)\n                continue\n            principal = self.mtool.getMemberById(principal_id)\n            if principal is not None:\n                userResults.append(principal)\n\n        groupResults.sort(key=lambda x: normalizeString(x.getGroupTitleOrName()))\n        userResults.sort(key=lambda x: normalizeString(x.getProperty('fullname') or ''))\n\n        return groupResults + userResults\n\n    def getPotentialMembers(self, searchString):\n        ignoredUsersGroups = [\n            x.id for x in self.getMembers() + [self.group, ] if x is not None]\n        return self.membershipSearch(searchString, ignore=ignoredUsersGroups)\n", "path": "Products/CMFPlone/controlpanel/browser/usergroups_groupmembership.py"}]}