prompt: We are currently solving the following issue within our repository. Here is the issue text:
  --- BEGIN ISSUE ---
  Allow to hide/show actions directly from the Actions control panel list
  As @esteele mentionned in #1342
  
  
  --- 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/actions.py`
  Content:
  ```
  1 from plone.autoform.form import AutoExtensibleForm
  2 from Products.CMFCore.ActionInformation import Action
  3 from Products.CMFCore.interfaces import IAction, IActionCategory
  4 from Products.CMFCore.utils import getToolByName
  5 from Products.CMFPlone import PloneMessageFactory as _
  6 from Products.CMFPlone.interfaces import IActionSchema, INewActionSchema
  7 from Products.Five import BrowserView
  8 from Products.Five.browser.pagetemplatefile import ViewPageTemplateFile
  9 from z3c.form import form
  10 from zope.component import adapts
  11 from zope.event import notify
  12 from zope.interface import implements
  13 from zope.lifecycleevent import ObjectCreatedEvent
  14 
  15 
  16 class ActionListControlPanel(BrowserView):
  17     """Control panel for the portal actions."""
  18 
  19     template = ViewPageTemplateFile("actions.pt")
  20 
  21     def __init__(self, context, request):
  22         self.context = context
  23         self.request = request
  24         self.portal_actions = getToolByName(self.context, 'portal_actions')
  25 
  26     def display(self):
  27         actions = []
  28         for category in self.portal_actions.objectValues():
  29             if category.id == 'controlpanel':
  30                 continue
  31             if not IActionCategory.providedBy(category):
  32                 continue
  33             cat_infos = {
  34                 'id': category.id,
  35                 'title': category.title or category.id,
  36             }
  37             action_list = []
  38             for action in category.objectValues():
  39                 if IAction.providedBy(action):
  40                     action_list.append({
  41                         'id': action.id,
  42                         'title': action.title,
  43                         'url': action.absolute_url(),
  44                     })
  45             cat_infos['actions'] = action_list
  46             actions.append(cat_infos)
  47 
  48         self.actions = actions
  49         return self.template()
  50 
  51     def __call__(self):
  52         if self.request.get('deleteaction'):
  53             action_id = self.request['deleteaction']
  54             category = self.portal_actions[self.request['category']]
  55             category.manage_delObjects([action_id])
  56             self.request.RESPONSE.redirect('@@actions-controlpanel')
  57         return self.display()
  58 
  59 
  60 class ActionControlPanelAdapter(object):
  61     """Adapter for action form."""
  62 
  63     adapts(IAction)
  64     implements(IActionSchema)
  65 
  66     def __init__(self, context):
  67         self.context = context
  68         self.current_category = self.context.getParentNode()
  69 
  70     def get_category(self):
  71         return self.current_category.id
  72 
  73     def set_category(self, value):
  74         portal_actions = getToolByName(self.context, 'portal_actions')
  75         new_category = portal_actions.get(value)
  76         cookie = self.current_category.manage_cutObjects(ids=[self.context.id])
  77         new_category.manage_pasteObjects(cookie)
  78 
  79     category = property(get_category, set_category)
  80 
  81     def get_title(self):
  82         return self.context.title
  83 
  84     def set_title(self, value):
  85         self.context._setPropValue('title', value)
  86 
  87     title = property(get_title, set_title)
  88 
  89     def get_description(self):
  90         return self.context.description
  91 
  92     def set_description(self, value):
  93         self.context._setPropValue('description', value)
  94 
  95     description = property(get_description, set_description)
  96 
  97     def get_i18n_domain(self):
  98         return self.context.i18n_domain
  99 
  100     def set_i18n_domain(self, value):
  101         self.context._setPropValue('i18n_domain', value)
  102 
  103     i18n_domain = property(get_i18n_domain, set_i18n_domain)
  104 
  105     def get_url_expr(self):
  106         return self.context.url_expr
  107 
  108     def set_url_expr(self, value):
  109         self.context._setPropValue('url_expr', value)
  110 
  111     url_expr = property(get_url_expr, set_url_expr)
  112 
  113     def get_available_expr(self):
  114         return self.context.available_expr
  115 
  116     def set_available_expr(self, value):
  117         self.context._setPropValue('available_expr', value)
  118 
  119     available_expr = property(get_available_expr, set_available_expr)
  120 
  121     def get_permissions(self):
  122         return self.context.permissions
  123 
  124     def set_permissions(self, value):
  125         self.context._setPropValue('permissions', value)
  126 
  127     permissions = property(get_permissions, set_permissions)
  128 
  129     def get_visible(self):
  130         return self.context.visible
  131 
  132     def set_visible(self, value):
  133         self.context._setPropValue('visible', value)
  134 
  135     visible = property(get_visible, set_visible)
  136 
  137     def get_position(self):
  138         position = self.current_category.objectIds().index(self.context.id)
  139         return position + 1
  140 
  141     def set_position(self, value):
  142         current_position = self.current_category.objectIds().index(
  143             self.context.id)
  144         all_actions = list(self.current_category._objects)
  145         current_action = all_actions.pop(current_position)
  146         new_position = value - 1
  147         all_actions = all_actions[0:new_position] + [current_action] + \
  148             all_actions[new_position:]
  149         self.current_category._objects = tuple(all_actions)
  150 
  151     position = property(get_position, set_position)
  152 
  153 
  154 class ActionControlPanel(AutoExtensibleForm, form.EditForm):
  155     """A form to edit a portal action."""
  156 
  157     schema = IActionSchema
  158     ignoreContext = False
  159     label = _(u'Action Settings')
  160 
  161 
  162 class NewActionControlPanel(AutoExtensibleForm, form.AddForm):
  163     """A form to add a new portal action."""
  164 
  165     schema = INewActionSchema
  166     ignoreContext = True
  167     label = _(u'New action')
  168 
  169     def createAndAdd(self, data):
  170         portal_actions = getToolByName(self.context, 'portal_actions')
  171         category = portal_actions.get(data['category'])
  172         action_id = data['id']
  173         action = Action(
  174             action_id,
  175             title=action_id,
  176             i18n_domain='plone',
  177             permissions=['View'],
  178         )
  179         category[action_id] = action
  180         notify(ObjectCreatedEvent(action))
  181
  ```
  --- 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()
  
  ```
  
golden_diff: diff --git a/Products/CMFPlone/controlpanel/browser/actions.py b/Products/CMFPlone/controlpanel/browser/actions.py
  --- a/Products/CMFPlone/controlpanel/browser/actions.py
  +++ b/Products/CMFPlone/controlpanel/browser/actions.py
  @@ -41,6 +41,7 @@
                           'id': action.id,
                           'title': action.title,
                           'url': action.absolute_url(),
  +                        'visible': action.visible,
                       })
               cat_infos['actions'] = action_list
               actions.append(cat_infos)
  @@ -49,11 +50,21 @@
           return self.template()
   
       def __call__(self):
  -        if self.request.get('deleteaction'):
  -            action_id = self.request['deleteaction']
  +        if self.request.get('delete'):
  +            action_id = self.request['actionid']
               category = self.portal_actions[self.request['category']]
               category.manage_delObjects([action_id])
               self.request.RESPONSE.redirect('@@actions-controlpanel')
  +        if self.request.get('hide'):
  +            action_id = self.request['actionid']
  +            category = self.portal_actions[self.request['category']]
  +            category[action_id].visible = False
  +            self.request.RESPONSE.redirect('@@actions-controlpanel')
  +        if self.request.get('show'):
  +            action_id = self.request['actionid']
  +            category = self.portal_actions[self.request['category']]
  +            category[action_id].visible = True
  +            self.request.RESPONSE.redirect('@@actions-controlpanel')
           return self.display()
  
verification_info: {"golden_diff": "diff --git a/Products/CMFPlone/controlpanel/browser/actions.py b/Products/CMFPlone/controlpanel/browser/actions.py\n--- a/Products/CMFPlone/controlpanel/browser/actions.py\n+++ b/Products/CMFPlone/controlpanel/browser/actions.py\n@@ -41,6 +41,7 @@\n                         'id': action.id,\n                         'title': action.title,\n                         'url': action.absolute_url(),\n+                        'visible': action.visible,\n                     })\n             cat_infos['actions'] = action_list\n             actions.append(cat_infos)\n@@ -49,11 +50,21 @@\n         return self.template()\n \n     def __call__(self):\n-        if self.request.get('deleteaction'):\n-            action_id = self.request['deleteaction']\n+        if self.request.get('delete'):\n+            action_id = self.request['actionid']\n             category = self.portal_actions[self.request['category']]\n             category.manage_delObjects([action_id])\n             self.request.RESPONSE.redirect('@@actions-controlpanel')\n+        if self.request.get('hide'):\n+            action_id = self.request['actionid']\n+            category = self.portal_actions[self.request['category']]\n+            category[action_id].visible = False\n+            self.request.RESPONSE.redirect('@@actions-controlpanel')\n+        if self.request.get('show'):\n+            action_id = self.request['actionid']\n+            category = self.portal_actions[self.request['category']]\n+            category[action_id].visible = True\n+            self.request.RESPONSE.redirect('@@actions-controlpanel')\n         return self.display()\n", "issue": "Allow to hide/show actions directly from the Actions control panel list\nAs @esteele mentionned in #1342\n\n", "before_files": [{"content": "from plone.autoform.form import AutoExtensibleForm\nfrom Products.CMFCore.ActionInformation import Action\nfrom Products.CMFCore.interfaces import IAction, IActionCategory\nfrom Products.CMFCore.utils import getToolByName\nfrom Products.CMFPlone import PloneMessageFactory as _\nfrom Products.CMFPlone.interfaces import IActionSchema, INewActionSchema\nfrom Products.Five import BrowserView\nfrom Products.Five.browser.pagetemplatefile import ViewPageTemplateFile\nfrom z3c.form import form\nfrom zope.component import adapts\nfrom zope.event import notify\nfrom zope.interface import implements\nfrom zope.lifecycleevent import ObjectCreatedEvent\n\n\nclass ActionListControlPanel(BrowserView):\n    \"\"\"Control panel for the portal actions.\"\"\"\n\n    template = ViewPageTemplateFile(\"actions.pt\")\n\n    def __init__(self, context, request):\n        self.context = context\n        self.request = request\n        self.portal_actions = getToolByName(self.context, 'portal_actions')\n\n    def display(self):\n        actions = []\n        for category in self.portal_actions.objectValues():\n            if category.id == 'controlpanel':\n                continue\n            if not IActionCategory.providedBy(category):\n                continue\n            cat_infos = {\n                'id': category.id,\n                'title': category.title or category.id,\n            }\n            action_list = []\n            for action in category.objectValues():\n                if IAction.providedBy(action):\n                    action_list.append({\n                        'id': action.id,\n                        'title': action.title,\n                        'url': action.absolute_url(),\n                    })\n            cat_infos['actions'] = action_list\n            actions.append(cat_infos)\n\n        self.actions = actions\n        return self.template()\n\n    def __call__(self):\n        if self.request.get('deleteaction'):\n            action_id = self.request['deleteaction']\n            category = self.portal_actions[self.request['category']]\n            category.manage_delObjects([action_id])\n            self.request.RESPONSE.redirect('@@actions-controlpanel')\n        return self.display()\n\n\nclass ActionControlPanelAdapter(object):\n    \"\"\"Adapter for action form.\"\"\"\n\n    adapts(IAction)\n    implements(IActionSchema)\n\n    def __init__(self, context):\n        self.context = context\n        self.current_category = self.context.getParentNode()\n\n    def get_category(self):\n        return self.current_category.id\n\n    def set_category(self, value):\n        portal_actions = getToolByName(self.context, 'portal_actions')\n        new_category = portal_actions.get(value)\n        cookie = self.current_category.manage_cutObjects(ids=[self.context.id])\n        new_category.manage_pasteObjects(cookie)\n\n    category = property(get_category, set_category)\n\n    def get_title(self):\n        return self.context.title\n\n    def set_title(self, value):\n        self.context._setPropValue('title', value)\n\n    title = property(get_title, set_title)\n\n    def get_description(self):\n        return self.context.description\n\n    def set_description(self, value):\n        self.context._setPropValue('description', value)\n\n    description = property(get_description, set_description)\n\n    def get_i18n_domain(self):\n        return self.context.i18n_domain\n\n    def set_i18n_domain(self, value):\n        self.context._setPropValue('i18n_domain', value)\n\n    i18n_domain = property(get_i18n_domain, set_i18n_domain)\n\n    def get_url_expr(self):\n        return self.context.url_expr\n\n    def set_url_expr(self, value):\n        self.context._setPropValue('url_expr', value)\n\n    url_expr = property(get_url_expr, set_url_expr)\n\n    def get_available_expr(self):\n        return self.context.available_expr\n\n    def set_available_expr(self, value):\n        self.context._setPropValue('available_expr', value)\n\n    available_expr = property(get_available_expr, set_available_expr)\n\n    def get_permissions(self):\n        return self.context.permissions\n\n    def set_permissions(self, value):\n        self.context._setPropValue('permissions', value)\n\n    permissions = property(get_permissions, set_permissions)\n\n    def get_visible(self):\n        return self.context.visible\n\n    def set_visible(self, value):\n        self.context._setPropValue('visible', value)\n\n    visible = property(get_visible, set_visible)\n\n    def get_position(self):\n        position = self.current_category.objectIds().index(self.context.id)\n        return position + 1\n\n    def set_position(self, value):\n        current_position = self.current_category.objectIds().index(\n            self.context.id)\n        all_actions = list(self.current_category._objects)\n        current_action = all_actions.pop(current_position)\n        new_position = value - 1\n        all_actions = all_actions[0:new_position] + [current_action] + \\\n            all_actions[new_position:]\n        self.current_category._objects = tuple(all_actions)\n\n    position = property(get_position, set_position)\n\n\nclass ActionControlPanel(AutoExtensibleForm, form.EditForm):\n    \"\"\"A form to edit a portal action.\"\"\"\n\n    schema = IActionSchema\n    ignoreContext = False\n    label = _(u'Action Settings')\n\n\nclass NewActionControlPanel(AutoExtensibleForm, form.AddForm):\n    \"\"\"A form to add a new portal action.\"\"\"\n\n    schema = INewActionSchema\n    ignoreContext = True\n    label = _(u'New action')\n\n    def createAndAdd(self, data):\n        portal_actions = getToolByName(self.context, 'portal_actions')\n        category = portal_actions.get(data['category'])\n        action_id = data['id']\n        action = Action(\n            action_id,\n            title=action_id,\n            i18n_domain='plone',\n            permissions=['View'],\n        )\n        category[action_id] = action\n        notify(ObjectCreatedEvent(action))\n", "path": "Products/CMFPlone/controlpanel/browser/actions.py"}], "after_files": [{"content": "from plone.autoform.form import AutoExtensibleForm\nfrom Products.CMFCore.ActionInformation import Action\nfrom Products.CMFCore.interfaces import IAction, IActionCategory\nfrom Products.CMFCore.utils import getToolByName\nfrom Products.CMFPlone import PloneMessageFactory as _\nfrom Products.CMFPlone.interfaces import IActionSchema, INewActionSchema\nfrom Products.Five import BrowserView\nfrom Products.Five.browser.pagetemplatefile import ViewPageTemplateFile\nfrom z3c.form import form\nfrom zope.component import adapts\nfrom zope.event import notify\nfrom zope.interface import implements\nfrom zope.lifecycleevent import ObjectCreatedEvent\n\n\nclass ActionListControlPanel(BrowserView):\n    \"\"\"Control panel for the portal actions.\"\"\"\n\n    template = ViewPageTemplateFile(\"actions.pt\")\n\n    def __init__(self, context, request):\n        self.context = context\n        self.request = request\n        self.portal_actions = getToolByName(self.context, 'portal_actions')\n\n    def display(self):\n        actions = []\n        for category in self.portal_actions.objectValues():\n            if category.id == 'controlpanel':\n                continue\n            if not IActionCategory.providedBy(category):\n                continue\n            cat_infos = {\n                'id': category.id,\n                'title': category.title or category.id,\n            }\n            action_list = []\n            for action in category.objectValues():\n                if IAction.providedBy(action):\n                    action_list.append({\n                        'id': action.id,\n                        'title': action.title,\n                        'url': action.absolute_url(),\n                        'visible': action.visible,\n                    })\n            cat_infos['actions'] = action_list\n            actions.append(cat_infos)\n\n        self.actions = actions\n        return self.template()\n\n    def __call__(self):\n        if self.request.get('delete'):\n            action_id = self.request['actionid']\n            category = self.portal_actions[self.request['category']]\n            category.manage_delObjects([action_id])\n            self.request.RESPONSE.redirect('@@actions-controlpanel')\n        if self.request.get('hide'):\n            action_id = self.request['actionid']\n            category = self.portal_actions[self.request['category']]\n            category[action_id].visible = False\n            self.request.RESPONSE.redirect('@@actions-controlpanel')\n        if self.request.get('show'):\n            action_id = self.request['actionid']\n            category = self.portal_actions[self.request['category']]\n            category[action_id].visible = True\n            self.request.RESPONSE.redirect('@@actions-controlpanel')\n        return self.display()\n\n\nclass ActionControlPanelAdapter(object):\n    \"\"\"Adapter for action form.\"\"\"\n\n    adapts(IAction)\n    implements(IActionSchema)\n\n    def __init__(self, context):\n        self.context = context\n        self.current_category = self.context.getParentNode()\n\n    def get_category(self):\n        return self.current_category.id\n\n    def set_category(self, value):\n        portal_actions = getToolByName(self.context, 'portal_actions')\n        new_category = portal_actions.get(value)\n        cookie = self.current_category.manage_cutObjects(ids=[self.context.id])\n        new_category.manage_pasteObjects(cookie)\n\n    category = property(get_category, set_category)\n\n    def get_title(self):\n        return self.context.title\n\n    def set_title(self, value):\n        self.context._setPropValue('title', value)\n\n    title = property(get_title, set_title)\n\n    def get_description(self):\n        return self.context.description\n\n    def set_description(self, value):\n        self.context._setPropValue('description', value)\n\n    description = property(get_description, set_description)\n\n    def get_i18n_domain(self):\n        return self.context.i18n_domain\n\n    def set_i18n_domain(self, value):\n        self.context._setPropValue('i18n_domain', value)\n\n    i18n_domain = property(get_i18n_domain, set_i18n_domain)\n\n    def get_url_expr(self):\n        return self.context.url_expr\n\n    def set_url_expr(self, value):\n        self.context._setPropValue('url_expr', value)\n\n    url_expr = property(get_url_expr, set_url_expr)\n\n    def get_available_expr(self):\n        return self.context.available_expr\n\n    def set_available_expr(self, value):\n        self.context._setPropValue('available_expr', value)\n\n    available_expr = property(get_available_expr, set_available_expr)\n\n    def get_permissions(self):\n        return self.context.permissions\n\n    def set_permissions(self, value):\n        self.context._setPropValue('permissions', value)\n\n    permissions = property(get_permissions, set_permissions)\n\n    def get_visible(self):\n        return self.context.visible\n\n    def set_visible(self, value):\n        self.context._setPropValue('visible', value)\n\n    visible = property(get_visible, set_visible)\n\n    def get_position(self):\n        position = self.current_category.objectIds().index(self.context.id)\n        return position + 1\n\n    def set_position(self, value):\n        current_position = self.current_category.objectIds().index(\n            self.context.id)\n        all_actions = list(self.current_category._objects)\n        current_action = all_actions.pop(current_position)\n        new_position = value - 1\n        all_actions = all_actions[0:new_position] + [current_action] + \\\n            all_actions[new_position:]\n        self.current_category._objects = tuple(all_actions)\n\n    position = property(get_position, set_position)\n\n\nclass ActionControlPanel(AutoExtensibleForm, form.EditForm):\n    \"\"\"A form to edit a portal action.\"\"\"\n\n    schema = IActionSchema\n    ignoreContext = False\n    label = _(u'Action Settings')\n\n\nclass NewActionControlPanel(AutoExtensibleForm, form.AddForm):\n    \"\"\"A form to add a new portal action.\"\"\"\n\n    schema = INewActionSchema\n    ignoreContext = True\n    label = _(u'New action')\n\n    def createAndAdd(self, data):\n        portal_actions = getToolByName(self.context, 'portal_actions')\n        category = portal_actions.get(data['category'])\n        action_id = data['id']\n        action = Action(\n            action_id,\n            title=action_id,\n            i18n_domain='plone',\n            permissions=['View'],\n        )\n        category[action_id] = action\n        notify(ObjectCreatedEvent(action))\n", "path": "Products/CMFPlone/controlpanel/browser/actions.py"}]}