Passed
Push — master ( f3b189...cac864 )
by Jordi
16:43
created

BootstrapView.getColumnsClasses()   F

Complexity

Conditions 14

Size

Total Lines 50
Code Lines 25

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 25
dl 0
loc 50
rs 3.6
c 0
b 0
f 0
cc 14
nop 2

How to fix   Complexity   

Complexity

Complex classes like bika.lims.browser.bootstrap.bootstrap.BootstrapView.getColumnsClasses() often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

1
# -*- coding: utf-8 -*-
2
#
3
# This file is part of SENAITE.CORE.
4
#
5
# SENAITE.LIMS 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-2020 by it's authors.
19
# Some rights reserved, see README and LICENSE.
20
21
from bika.lims import api
22
from plone.memoize.ram import cache
23
from Products.Five import BrowserView
24
from senaite.lims import logger
25
from zope.component import getMultiAdapter
26
from zope.interface import Interface
27
from zope.interface import implements
28
29
30
class IBootstrapView(Interface):
31
    """Twitter Bootstrap View
32
    """
33
34
    def getColumnsClasses(view=None):
35
        """A helper method to return the clases for the columns of the site
36
           it should return a dict with three elements:'one', 'two', 'content'
37
           Each of them should contain the classnames for the first (leftmost)
38
           second (rightmost) and middle column
39
        """
40
41
    def getViewportValues(view=None):
42
        """Determine the value of the viewport meta-tag
43
        """
44
45
46
def icon_cache_key(method, self, brain_or_object):
47
    """Generates a cache key for the icon lookup
48
49
    Includes the virtual URL to handle multiple HTTP/HTTPS domains
50
    Example: http://senaite.local/clients?modified=1512033263370
51
    """
52
    url = api.get_url(brain_or_object)
53
    modified = api.get_modification_date(brain_or_object).millis()
54
    key = "{}?modified={}".format(url, modified)
55
    logger.debug("Generated Cache Key: {}".format(key))
56
    return key
57
58
59
class BootstrapView(BrowserView):
60
    """Twitter Bootstrap helper view for SENAITE LIMS
61
    """
62
    implements(IBootstrapView)
63
64
    def __init__(self, context, request):
65
        super(BrowserView, self).__init__(context, request)
66
67
    @cache(icon_cache_key)
68
    def get_icon_for(self, brain_or_object):
69
        """Get the navigation portlet icon for the brain or object
70
71
        The cache key ensures that the lookup is done only once per domain name
72
        """
73
        portal_types = api.get_tool("portal_types")
74
        fti = portal_types.getTypeInfo(api.get_portal_type(brain_or_object))
75
        icon = fti.getIcon()
76
        if not icon:
77
            return ""
78
        # Always try to get the big icon for high-res displays
79
        icon_big = icon.replace(".png", "_big.png")
80
        # fall back to a default icon if the looked up icon does not exist
81
        if self.context.restrictedTraverse(icon_big, None) is None:
82
            icon_big = None
83
        portal_url = api.get_url(api.get_portal())
84
        title = api.get_title(brain_or_object)
85
        html_tag = "<img title='{}' src='{}/{}' width='16' />".format(
86
            title, portal_url, icon_big or icon)
87
        logger.debug("Generated Icon Tag for {}: {}".format(
88
            api.get_path(brain_or_object), html_tag))
89
        return html_tag
90
91
    def getViewportValues(self, view=None):
92
        """Determine the value of the viewport meta-tag
93
        """
94
        values = {
95
            'width': 'device-width',
96
            'initial-scale': '1.0',
97
        }
98
99
        return ','.join('%s=%s' % (k, v) for k, v in values.items())
100
101
    def getColumnsClasses(self, view=None):
102
        """Determine whether a column should be shown. The left column is
103
           called plone.leftcolumn; the right column is called
104
           plone.rightcolumn.
105
        """
106
107
        plone_view = getMultiAdapter(
108
            (self.context, self.request), name=u'plone')
109
        portal_state = getMultiAdapter(
110
            (self.context, self.request), name=u'plone_portal_state')
111
112
        sl = plone_view.have_portlets('plone.leftcolumn', view=view)
113
        sr = plone_view.have_portlets('plone.rightcolumn', view=view)
114
115
        isRTL = portal_state.is_rtl()
116
117
        # pre-fill dictionary
118
        columns = dict(one="", content="", two="")
119
120
        if not sl and not sr:
121
            # we don't have columns, thus conten takes the whole width
122
            columns['content'] = "col-md-12"
123
124
        elif sl and sr:
125
            # In case we have both columns, content takes 50% of the whole
126
            # width and the rest 50% is spread between the columns
127
            columns['one'] = "col-xs-12 col-md-2"
128
            columns['content'] = "col-xs-12 col-md-8"
129
            columns['two'] = "col-xs-12 col-md-2"
130
131
        elif (sr and not sl) and not isRTL:
132
            # We have right column and we are NOT in RTL language
133
            columns['content'] = "col-xs-12 col-md-10"
134
            columns['two'] = "col-xs-12 col-md-2"
135
136
        elif (sl and not sr) and isRTL:
137
            # We have left column and we are in RTL language
138
            columns['one'] = "col-xs-12 col-md-2"
139
            columns['content'] = "col-xs-12 col-md-10"
140
141
        elif (sl and not sr) and not isRTL:
142
            # We have left column and we are in NOT RTL language
143
            columns['one'] = "col-xs-12 col-md-2"
144
            columns['content'] = "col-xs-12 col-md-10"
145
146
        # # append cell to each css-string
147
        # for key, value in columns.items():
148
        #     columns[key] = "cell " + value
149
150
        return columns
151