Passed
Push — master ( 6d6a8c...6374c8 )
by Ramon
05:17
created

bika.lims.browser.BrowserView.bika_catalog()   A

Complexity

Conditions 1

Size

Total Lines 3
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 3
dl 0
loc 3
rs 10
c 0
b 0
f 0
cc 1
nop 1
1
# -*- coding: utf-8 -*-
2
#
3
# This file is part of SENAITE.CORE
4
#
5
# Copyright 2018 by it's authors.
6
# Some rights reserved. See LICENSE.rst, CONTRIBUTORS.rst.
7
8
"""Bika's browser views are based on this one, for a nice set of utilities.
9
"""
10
import traceback
11
from datetime import datetime
12
from time import strptime
13
14
from AccessControl import ClassSecurityInfo
15
from DateTime.DateTime import DateTime, safelocaltime
16
from Products.ATContentTypes.utils import dt2DT
17
from Products.CMFCore.utils import getToolByName
18
from Products.CMFPlone.i18nl10n import ulocalized_time as _ut
19
from Products.Five.browser import BrowserView as BaseBrowserView
20
from bika.lims import logger
21
from zope.cachedescriptors.property import Lazy as lazy_property
22
from zope.i18n import translate
23
24
25
def get_date(context, value):
26
    """Tries to return a DateTime.DateTime object
27
    """
28
    if not value:
29
        return None
30
    if isinstance(value, DateTime):
31
        return value
32
    if isinstance(value, datetime):
33
        return dt2DT(value)
34
    if not isinstance(value, basestring):
35
        return None
36
37
    def try_parse(date_string, format):
38
        if not format:
39
            return None
40
        try:
41
            struct_time = strptime(date_string, format)
42
            return datetime(*struct_time[:6])
43
        except ValueError:
44
            pass
45
        return None
46
47
    def get_locale_format(key, context):
48
        format = context.translate(key, domain="senaite.core", mapping={})
49
        # TODO: Is this replacement below strictly necessary?
50
        return format.replace(r"${", '%').replace('}', '')
51
52
    # Try with prioritized formats
53
    formats = [get_locale_format("date_format_long", context),
54
               get_locale_format("date_format_short", context),
55
               "%Y-%m-%d %H:%M", "%Y-%m-%d", "%Y-%m-%d %H:%M:%S"]
56
    for pri_format in formats:
57
        val = try_parse(value, pri_format)
58
        if not val:
59
            continue
60
        val = dt2DT(val)
61
        if val.timezoneNaive():
62
            # Use local timezone for tz naive strings
63
            # see http://dev.plone.org/plone/ticket/10141
64
            zone = val.localZone(safelocaltime(val.timeTime()))
65
            parts = val.parts()[:-1] + (zone,)
66
            val = DateTime(*parts)
67
        return val
68
69
    logger.warn("Unable to convert {} to datetime".format(value))
70
    return None
71
72
73
def ulocalized_time(time, long_format=None, time_only=None, context=None,
74
                    request=None):
75
    """
76
    This function gets ans string as time or a DateTime objects and returns a
77
    string with the time formatted
78
79
    :param time: The time to process
80
    :type time: str/DateTime
81
    :param long_format:  If True, return time in ling format
82
    :type portal_type: boolean/null
83
    :param time_only: If True, only returns time.
84
    :type title: boolean/null
85
    :param context: The current context
86
    :type context: ATContentType
87
    :param request: The current request
88
    :type request: HTTPRequest object
89
    :returns: The formatted date as string
90
    :rtype: string
91
    """
92
    # if time is a string, we'll try pass it through strptime with the various
93
    # formats defined.
94
    time = get_date(context, time)
95
    if not time or not isinstance(time, DateTime):
96
        return ''
97
98
    # no printing times if they were not specified in inputs
99
    if time.second() + time.minute() + time.hour() == 0:
100
        long_format = False
101
    try:
102
        time_str = _ut(time, long_format, time_only, context, 'senaite.core', request)
103
    except ValueError:
104
        err_msg = traceback.format_exc() + '\n'
105
        logger.warn(
106
            err_msg + '\n' +
107
            "Error converting '{}' time to string in {}."
108
            .format(time, context))
109
        time_str = ''
110
    return time_str
111
112
113
114
class BrowserView(BaseBrowserView):
115
    security = ClassSecurityInfo()
116
117
    logger = logger
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable logger does not seem to be defined.
Loading history...
118
119
    def __init__(self, context, request):
120
        self.context = context
121
        self.request = request
122
        super(BrowserView, self).__init__(context, request)
123
124
    security.declarePublic('ulocalized_time')
125
126
    def ulocalized_time(self, time, long_format=None, time_only=None):
127
        return ulocalized_time(time, long_format, time_only,
128
                               context=self.context, request=self.request)
129
130
    @lazy_property
131
    def portal(self):
132
        return getToolByName(self.context, 'portal_url').getPortalObject()
133
134
    @lazy_property
135
    def portal_url(self):
136
        return self.portal.absolute_url().split("?")[0]
137
138
    @lazy_property
139
    def portal_catalog(self):
140
        return getToolByName(self.context, 'portal_catalog')
141
142
    @lazy_property
143
    def reference_catalog(self):
144
        return getToolByName(self.context, 'reference_catalog')
145
146
    @lazy_property
147
    def bika_analysis_catalog(self):
148
        return getToolByName(self.context, 'bika_analysis_catalog')
149
150
    @lazy_property
151
    def bika_setup_catalog(self):
152
        return getToolByName(self.context, 'bika_setup_catalog')
153
154
    @lazy_property
155
    def bika_catalog(self):
156
        return getToolByName(self.context, 'bika_catalog')
157
158
    @lazy_property
159
    def portal_membership(self):
160
        return getToolByName(self.context, 'portal_membership')
161
162
    @lazy_property
163
    def portal_groups(self):
164
        return getToolByName(self.context, 'portal_groups')
165
166
    @lazy_property
167
    def portal_workflow(self):
168
        return getToolByName(self.context, 'portal_workflow')
169
170
    @lazy_property
171
    def checkPermission(self, perm, obj):
172
        return self.portal_membership.checkPermission(perm, obj)
173
174
    # TODO: user_fullname is deprecated and will be removed in Bika LIMS 3.3.
175
    # Use bika.utils.user_fullnameinstead
176
    # I was having a problem trying to import the function from bika.lims.utils
177
    # so i copied the code here.
178
    def user_fullname(self, userid):
179
        member = self.portal_membership.getMemberById(userid)
180
        if member is None:
181
            return userid
182
        member_fullname = member.getProperty('fullname')
183
        portal_catalog = getToolByName(self, 'portal_catalog')
184
        c = portal_catalog(portal_type='Contact', getUsername=userid)
185
        contact_fullname = c[0].getObject().getFullname() if c else None
186
        return contact_fullname or member_fullname or userid
187
188
    # TODO: user_fullname is deprecated and will be removed in Bika LIMS 3.3.
189
    # Use bika.utils.user_fullnameinstead.
190
    # I was having a problem trying to import the function from bika.lims.utils
191
    # so i copied the code here.
192
    def user_email(self, userid):
193
        member = self.portal_membership.getMemberById(userid)
194
        if member is None:
195
            return userid
196
        member_email = member.getProperty('email')
197
        portal_catalog = getToolByName(self, 'portal_catalog')
198
        c = portal_catalog(portal_type='Contact', getUsername=userid)
199
        contact_email = c[0].getObject().getEmailAddress() if c else None
200
        return contact_email or member_email or ''
201
202
    def python_date_format(self, long_format=None, time_only=False):
203
        """This convert bika domain date format msgstrs to Python
204
        strftime format strings, by the same rules as ulocalized_time.
205
        XXX i18nl10n.py may change, and that is where this code is taken from.
206
        """
207
        # get msgid
208
        msgid = long_format and 'date_format_long' or 'date_format_short'
209
        if time_only:
210
            msgid = 'time_format'
211
        # get the formatstring
212
        formatstring = translate(msgid, domain="senaite.core",
213
                                 context=self.request)
214
215
        if formatstring is None or formatstring.startswith(
216
                'date_') or formatstring.startswith('time_'):
217
            self.logger.error("bika/%s/%s could not be translated" %
218
                              (self.request.get('LANGUAGE'), msgid))
219
            # msg catalog was not able to translate this msgids
220
            # use default setting
221
            properties = getToolByName(self.context,
222
                                       'portal_properties').site_properties
223
            if long_format:
224
                format = properties.localLongTimeFormat
225
            else:
226
                if time_only:
227
                    format = properties.localTimeOnlyFormat
228
                else:
229
                    format = properties.localTimeFormat
230
            return format
231
        return formatstring.replace(r"${", '%').replace('}', '')
232
233
    @lazy_property
234
    def date_format_long(self):
235
        fmt = self.python_date_format(long_format=1)
236
        if fmt == "date_format_long":
237
            fmt = "%Y-%m-%d %I:%M %p"
238
        return fmt
239
240
    @lazy_property
241
    def date_format_short(self):
242
        fmt = self.python_date_format()
243
        if fmt == "date_format_short":
244
            fmt = "%Y-%m-%d"
245
        return fmt
246
247
    @lazy_property
248
    def time_format(self):
249
        fmt = self.python_date_format(time_only=True)
250
        if fmt == "time_format":
251
            fmt = "%I:%M %p"
252
        return fmt
253