-
Notifications
You must be signed in to change notification settings - Fork 3
/
logo_view.py
136 lines (118 loc) · 5.2 KB
/
logo_view.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
from ftw.logo.converter import SCALES
from ftw.logo.converter import flatten_scales
from ftw.logo.interfaces import IIconConfig
from ftw.logo.interfaces import ILogo
from ftw.logo.interfaces import ILogoConfig
from ftw.logo.manual_override import OVERRIDES_FIXED_ID
from ftw.logo.manual_override import OVERRIDES_KEY_PATTERN
from ftw.logo.StringIOStreamIterator import StringIOStreamIterator
from plone.app.layout.globals.interfaces import IViewView
from plone.namedfile.browser import DisplayFile
from Products.Five.browser import BrowserView
from zExceptions import BadRequest
from zExceptions import NotFound
from zope.annotation.interfaces import IAnnotations
from zope.component import getMultiAdapter
from zope.interface import implementer
from zope.publisher.interfaces import IPublishTraverse
import mimetypes
CONFIGS = {
'logo': ILogoConfig,
'icon': IIconConfig,
}
@implementer(IPublishTraverse, IViewView)
class LogoView(BrowserView):
def __init__(self, context, request):
super(LogoView, self).__init__(context, request)
self.scale = None
self.config = None
self.zcml_only = None
def publishTraverse(self, request, name):
if self.zcml_only is None and self.config is None and name == 'z':
self.zcml_only = True
return self
elif self.config is None and name in CONFIGS:
self.config_name = name
self.config = CONFIGS[name]
return self
elif self.config and name in flatten_scales(SCALES):
self.scale = name
return self
elif self.config and name == 'get_logo':
self.scale = name
return self
else:
raise NotFound()
def __call__(self):
if not self.config or not self.scale:
raise BadRequest()
if self.scale == 'get_logo':
return self.handle_get_logo()
check_overrides = not self.zcml_only
return ((check_overrides and self.get_dx_overridden_image()) or
self.get_zcml_configured_image())
def get_dx_overridden_image(self):
overridesItem = self.context.get(OVERRIDES_FIXED_ID)
if overridesItem is None:
return None
# check if requested scale has been overridden and return it
field_name = '{}_{}'.format(self.config_name, self.scale)
field = getattr(overridesItem, field_name)
if not field:
# check if base logo/icon has been overridden, then return the transformed BASE logo/icon
base_field_name = '{}_BASE'.format(self.config_name)
if getattr(overridesItem, base_field_name):
annotations = IAnnotations(overridesItem)
config = annotations.get(OVERRIDES_KEY_PATTERN.format(self.config_name), None)
if config:
return self.show_config_scale(config)
if not field:
return None
display_file = DisplayFile(overridesItem, self.request).publishTraverse(self.request, field_name or base_field_name)
return display_file()
def get_zcml_configured_image(self):
config = getMultiAdapter(
(self.context, self.request), ILogo).get_config(self.config)
return self.show_config_scale(config)
def show_config_scale(self, config):
scale = config.get_scale(self.scale)
response = self.request.response
iterator = StringIOStreamIterator(scale['data'])
extension = scale.get('extension') or scale['format'].lower()
contenttype = mimetypes.types_map.get('.{}'.format(extension),
'application/octet-stream')
response.setHeader('X-Theme-Disabled', 'True')
charset = '' if contenttype == 'application/octet-stream' else 'charset=utf-8'
response.setHeader(
'Content-Type', '{}; {}'.format(contenttype, charset))
response.setHeader('Content-Length', iterator.len)
if self.request.get('r'):
# Do not set cache headers when no cachekey provided.
# The cached representation is to be considered fresh for 1 year
# http://stackoverflow.com/a/3001556/880628
response.setHeader('Cache-Control', 'public, max-age=31536000')
return iterator
def handle_get_logo(self):
if self.has_dx_logo() and not self.has_dx_base():
self.scale = 'LOGO'
return self.get_dx_overridden_image()
elif self.has_dx_base():
self.scale = 'BASE'
return self.get_dx_overridden_image()
else:
self.scale = 'BASE'
config = getMultiAdapter(
(self.context, self.request), ILogo).get_config(self.config)
if config.primary_logo_scale:
self.scale = config.primary_logo_scale.upper()
return self.get_zcml_configured_image()
def has_dx_logo(self):
overridesItem = self.context.get(OVERRIDES_FIXED_ID)
if not overridesItem:
return False
return bool(overridesItem.logo_LOGO)
def has_dx_base(self):
overridesItem = self.context.get(OVERRIDES_FIXED_ID)
if not overridesItem:
return False
return bool(overridesItem.logo_BASE)