Passed
Pull Request — 2.x (#1911)
by Ramon
04:47
created

bika.lims.setuphandlers.add_dexterity_items()   A

Complexity

Conditions 4

Size

Total Lines 13
Code Lines 8

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 8
dl 0
loc 13
rs 10
c 0
b 0
f 0
cc 4
nop 2
1
# -*- coding: utf-8 -*-
2
#
3
# This file is part of SENAITE.CORE.
4
#
5
# SENAITE.CORE is free software: you can redistribute it and/or modify it under
6
# the terms of the GNU General Public License as published by the Free Software
7
# Foundation, version 2.
8
#
9
# This program is distributed in the hope that it will be useful, but WITHOUT
10
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
11
# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
12
# details.
13
#
14
# You should have received a copy of the GNU General Public License along with
15
# this program; if not, write to the Free Software Foundation, Inc., 51
16
# Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
17
#
18
# Copyright 2018-2021 by it's authors.
19
# Some rights reserved, see README and LICENSE.
20
21
import itertools
22
23
from Acquisition import aq_base
24
from bika.lims import api
25
from bika.lims import logger
26
from plone import api as ploneapi
27
28
PROFILE_ID = "profile-bika.lims:default"
29
30
GROUPS = [
31
    {
32
        "id": "Analysts",
33
        "title": "Analysts",
34
        "roles": ["Analyst"],
35
    }, {
36
        "id": "Clients",
37
        "title": "Clients",
38
        "roles": ["Client"],
39
    }, {
40
        "id": "LabClerks",
41
        "title": "Lab Clerks",
42
        "roles": ["LabClerk"],
43
    }, {
44
        "id": "LabManagers",
45
        "title": "Lab Managers",
46
        "roles": ["LabManager"],
47
    }, {
48
        "id": "Preservers",
49
        "title": "Preservers",
50
        "roles": ["Preserver"],
51
    }, {
52
        "id": "Publishers",
53
        "title": "Publishers",
54
        "roles": ["Publisher"],
55
    }, {
56
        "id": "Verifiers",
57
        "title": "Verifiers",
58
        "roles": ["Verifier"],
59
    }, {
60
        "id": "Samplers",
61
        "title": "Samplers",
62
        "roles": ["Sampler"],
63
    }, {
64
        "id": "RegulatoryInspectors",
65
        "title": "Regulatory Inspectors",
66
        "roles": ["RegulatoryInspector"],
67
    }, {
68
        "id": "SamplingCoordinators",
69
        "title": "Sampling Coordinator",
70
        "roles": ["SamplingCoordinator"],
71
    }
72
]
73
74
NAV_BAR_ITEMS_TO_HIDE = (
75
    # List of items to hide from navigation bar
76
    "pricelists",
77
)
78
79
80
CONTENTS_TO_DELETE = (
81
    # List of items to delete
82
    "Members",
83
    "news",
84
    "events",
85
)
86
87
ALLOWED_STYLES = [
88
    "color",
89
    "background-color"
90
]
91
92
93
def setup_handler(context):
94
    """SENAITE setup handler
95
    """
96
97
    if context.readDataFile("bika.lims_various.txt") is None:
98
        return
99
100
    logger.info("SENAITE setup handler [BEGIN]")
101
102
    portal = context.getSite()
103
104
    # Run Installers
105
    hide_navbar_items(portal)
106
    reindex_content_structure(portal)
107
    setup_groups(portal)
108
    # XXX P5: Fix HTML filtering
109
    # setup_html_filter(portal)
110
111
    # Set CMF Form actions
112
    setup_form_controller_actions(portal)
113
114
    logger.info("SENAITE setup handler [DONE]")
115
116
117
def hide_navbar_items(portal):
118
    """Hide root items in navigation
119
    """
120
    logger.info("*** Hide Navigation Items ***")
121
122
    # Get the list of object ids for portal
123
    object_ids = portal.objectIds()
124
    object_ids = filter(lambda id: id in object_ids, NAV_BAR_ITEMS_TO_HIDE)
125
    for object_id in object_ids:
126
        item = portal[object_id]
127
        item.setExcludeFromNav(True)
128
        item.reindexObject()
129
130
131
def reindex_content_structure(portal):
132
    """Reindex contents generated by Generic Setup
133
    """
134
    logger.info("*** Reindex content structure ***")
135
136
    def reindex(obj, recurse=False):
137
        # skip catalog tools etc.
138
        if api.is_object(obj):
139
            obj.reindexObject()
140
        if recurse and hasattr(aq_base(obj), "objectValues"):
141
            map(reindex, obj.objectValues())
142
143
    setup = api.get_setup()
144
    setupitems = setup.objectValues()
145
    rootitems = portal.objectValues()
146
147
    for obj in itertools.chain(setupitems, rootitems):
148
        logger.info("Reindexing {}".format(repr(obj)))
149
        reindex(obj)
150
151
152
def setup_groups(portal):
153
    """Setup roles and groups
154
    """
155
    logger.info("*** Setup Roles and Groups ***")
156
157
    portal_groups = api.get_tool("portal_groups")
158
159
    for gdata in GROUPS:
160
        group_id = gdata["id"]
161
        # create the group and grant the roles
162
        if group_id not in portal_groups.listGroupIds():
163
            logger.info("+++ Adding group {title} ({id})".format(**gdata))
164
            portal_groups.addGroup(group_id,
165
                                   title=gdata["title"],
166
                                   roles=gdata["roles"])
167
        # grant the roles to the existing group
168
        else:
169
            ploneapi.group.grant_roles(
170
                groupname=gdata["id"],
171
                roles=gdata["roles"],)
172
            logger.info("+++ Granted group {title} ({id}) the roles {roles}"
173
                        .format(**gdata))
174
175
176
def setup_form_controller_actions(portal):
177
    """Setup custom CMF Form actions
178
    """
179
    logger.info("*** Setup Form Controller custom actions ***")
180
    fc_tool = api.get_tool("portal_form_controller")
181
182
    # Redirect the user to Worksheets listing view after the "remove" action
183
    # from inside Worksheet context is pressed
184
    # https://github.com/senaite/senaite.core/pull/1480
185
    fc_tool.addFormAction(
186
        object_id="content_status_modify",
187
        status="success",
188
        context_type="Worksheet",
189
        button=None,
190
        action_type="redirect_to",
191
        action_arg="python:object.aq_inner.aq_parent.absolute_url()")
192
193
194
def setup_html_filter(portal):
195
    """Setup HTML filtering for resultsinterpretations
196
    """
197
    logger.info("*** Setup HTML Filter ***")
198
    # XXX P5: Fix ImportError: No module named controlpanel.filter
199
    from plone.app.controlpanel.filter import IFilterSchema
200
    # bypass the broken API from portal_transforms
201
    adapter = IFilterSchema(portal)
202
    style_whitelist = adapter.style_whitelist
203
    for style in ALLOWED_STYLES:
204
        logger.info("Allow style '{}'".format(style))
205
        if style not in style_whitelist:
206
            style_whitelist.append(style)
207
    adapter.style_whitelist = style_whitelist
208