Passed
Push — 2.x ( 0ba30f...7ab1ba )
by Jordi
08:49
created

TemporaryContext.create_temporary_context()   A

Complexity

Conditions 4

Size

Total Lines 24
Code Lines 19

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 19
dl 0
loc 24
rs 9.45
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-2024 by it's authors.
19
# Some rights reserved, see README and LICENSE.
20
21
from bika.lims import api
22
from Products.Five.browser import BrowserView
23
from zope.component import getUtility
24
from zope.component.interfaces import IFactory
25
from zope.interface import implementer
26
from zope.publisher.interfaces import IPublishTraverse
27
28
29
@implementer(IPublishTraverse)
30
class TemporaryContext(BrowserView):
31
    """Browser view that provides a temporary AT/Dexterity context
32
    """
33
34
    def __init__(self, context, request):
35
        super(TemporaryContext, self).__init__(context, request)
36
        self.traverse_subpath = []
37
38
    def publishTraverse(self, request, name):
39
        """Called before __call__ for each path name and allows to dispatch
40
        subpaths to methods
41
        """
42
        self.traverse_subpath.append(name)
43
        return self
44
45
    def __call__(self):
46
        if len(self.traverse_subpath) == 0:
47
            raise TypeError("No portal type provided")
48
49
        # we expect the portal_type on the first position
50
        portal_type = self.traverse_subpath[0]
51
        context = self.create_temporary_context(portal_type)
52
        # call the context to return the rendered html
53
        return context()
54
55
    def create_temporary_context(self, portal_type):
56
        portal_types = api.get_tool("portal_types")
57
        if portal_type not in portal_types:
58
            raise TypeError("'%s' is not a valid portal_type" % portal_type)
59
        fti = portal_types[portal_type]
60
        tmp_id = "%s_temporary" % portal_type
61
        if fti.product:
62
            factory = fti._getFactoryMethod(self.context, check_security=0)
63
            factory(tmp_id)
64
            context = self.context[tmp_id]
65
            # remove the temporary created object
66
            self.context._delOb(tmp_id)
67
        else:
68
            factory = getUtility(IFactory, fti.factory)
69
            context = factory(tmp_id)
70
        # hook into acquisition chain
71
        context = context.__of__(self.context)
72
        # mark the context as temporary
73
        api.mark_temporary(context)
74
        # Traverse any further paths
75
        if len(self.traverse_subpath) > 1:
76
            path = "/".join(self.traverse_subpath[1:])
77
            context = context.unrestrictedTraverse(path)
78
        return context
79