1 | from Acquisition import aq_parent |
---|
2 | from Products.CMFCore.utils import getToolByName |
---|
3 | from Products.CacheSetup.config import log, CACHE_TOOL_ID, PLONE25 |
---|
4 | from patch_utils import wrap_method, call_pattern |
---|
5 | from cmf_utils import _checkConditionalGET, _setCacheHeaders |
---|
6 | try: |
---|
7 | from Products.PageTemplates.DeferExpr import LazyWrapper |
---|
8 | except: |
---|
9 | LazyWrapper = None |
---|
10 | |
---|
11 | if PLONE25: |
---|
12 | from StringIO import StringIO |
---|
13 | from zope.app.publisher.interfaces.browser import IBrowserView |
---|
14 | else: |
---|
15 | from Products.CMFPlone.patches.unicodehacks import FasterStringIO as StringIO |
---|
16 | from zope.publisher.interfaces.browser import IBrowserView |
---|
17 | |
---|
18 | #### patch FSPageTemplate.pt_render |
---|
19 | |
---|
20 | # Goal: if a 304 can be determined, rendering the template is cut |
---|
21 | # off. Otherwise cache headers are set. |
---|
22 | |
---|
23 | from Products.CMFCore.FSPageTemplate import FSPageTemplate |
---|
24 | |
---|
25 | def FSPT_pt_render(self, source=0, extra_context={}): |
---|
26 | pcs = getToolByName(self, CACHE_TOOL_ID, None) |
---|
27 | # if portal_cache_settings not in place, fall back to the old method |
---|
28 | if pcs is None or not pcs.getEnabled(): |
---|
29 | return call_pattern(self, 'pt_render', '__CacheSetup_FSPageTemplate_%s__', source, extra_context) |
---|
30 | |
---|
31 | self._updateFromFS() # Make sure the template has been loaded. |
---|
32 | |
---|
33 | if not source: |
---|
34 | request = self.REQUEST |
---|
35 | object = self.getParentNode() |
---|
36 | view = self.getId() |
---|
37 | member = pcs.getMember() |
---|
38 | (rule, header_set) = pcs.getRuleAndHeaderSet(request, object, view, member) |
---|
39 | if header_set is not None: |
---|
40 | expr_context = rule._getExpressionContext(request, object, view, member, keywords=extra_context) |
---|
41 | else: |
---|
42 | expr_context = None |
---|
43 | |
---|
44 | # If we have a conditional get, set status 304 and return |
---|
45 | # no content |
---|
46 | if _checkConditionalGET(self, extra_context, rule, header_set, expr_context): |
---|
47 | if PLONE25: |
---|
48 | return '' |
---|
49 | return u'' |
---|
50 | |
---|
51 | result = FSPageTemplate.inheritedAttribute('pt_render')( |
---|
52 | self, source, extra_context |
---|
53 | ) |
---|
54 | if not source: |
---|
55 | _setCacheHeaders(self, extra_context, rule, header_set, expr_context) |
---|
56 | return result |
---|
57 | |
---|
58 | #### patch PageTemplate.pt_render |
---|
59 | |
---|
60 | # Goal: actually set the 304 reponse header if applicable. |
---|
61 | |
---|
62 | from Products.PageTemplates.Expressions import getEngine |
---|
63 | if PLONE25: |
---|
64 | from TAL.TALInterpreter import TALInterpreter |
---|
65 | from Products.PageTemplates.PageTemplate import \ |
---|
66 | PageTemplateTracebackSupplement, PTRuntimeError |
---|
67 | else: |
---|
68 | from zope.tal.talinterpreter import TALInterpreter |
---|
69 | from zope.pagetemplate.pagetemplate import \ |
---|
70 | PageTemplateTracebackSupplement, PTRuntimeError |
---|
71 | |
---|
72 | def PT_pt_render(self, source=0, extra_context={}): |
---|
73 | """Render this Page Template""" |
---|
74 | pcs = getToolByName(self, CACHE_TOOL_ID, None) |
---|
75 | # if portal_cache_settings not in place, fall back to the old method |
---|
76 | if pcs is None or not pcs.getEnabled(): |
---|
77 | return call_pattern(self, 'pt_render', '__CacheSetup_PageTemplate_%s__', source, extra_context) |
---|
78 | |
---|
79 | if not self._v_cooked: |
---|
80 | self._cook() |
---|
81 | __traceback_supplement__ = (PageTemplateTracebackSupplement, self, self.pt_getContext()) |
---|
82 | |
---|
83 | if self._v_errors: |
---|
84 | e = str(self._v_errors) |
---|
85 | raise PTRuntimeError, ( |
---|
86 | 'Page Template %s has errors: %s' % (self.id, e)) |
---|
87 | |
---|
88 | if not source: |
---|
89 | # If we have a conditional get, set status 304 and return no |
---|
90 | # content |
---|
91 | request = self.REQUEST |
---|
92 | object = self.getParentNode() |
---|
93 | |
---|
94 | # we may get this if we have a Zope 3 browser view |
---|
95 | if IBrowserView.providedBy(object): |
---|
96 | view = getattr(object, '__name__', request['ACTUAL_URL'].split('/')[-1]) |
---|
97 | object = aq_parent(object) |
---|
98 | else: |
---|
99 | view = self.getId() |
---|
100 | view = str(view) |
---|
101 | |
---|
102 | member = pcs.getMember() |
---|
103 | (rule, header_set) = pcs.getRuleAndHeaderSet(request, object, view, member) |
---|
104 | if header_set is not None: |
---|
105 | expr_context = rule._getExpressionContext(request, object, view, member, keywords=extra_context) |
---|
106 | else: |
---|
107 | expr_context = None |
---|
108 | |
---|
109 | if _checkConditionalGET(self, extra_context, rule, header_set, expr_context): |
---|
110 | if PLONE25: |
---|
111 | return '' |
---|
112 | return u'' |
---|
113 | |
---|
114 | if PLONE25: |
---|
115 | output = self.StringIO() |
---|
116 | else: |
---|
117 | output = StringIO(u'') |
---|
118 | |
---|
119 | c = self.pt_getContext() |
---|
120 | c.update(extra_context) |
---|
121 | |
---|
122 | context = getEngine().getContext(c) |
---|
123 | TALInterpreter(self._v_program, self._v_macros, |
---|
124 | context, |
---|
125 | output, |
---|
126 | tal=not source, strictinsert=0)() |
---|
127 | |
---|
128 | # The following looks like it was left over from when we still did macro caching |
---|
129 | # I'm commenting it out for now as I don't think we do lazy expressions in cachefu anymore |
---|
130 | # |
---|
131 | ##clean up - XXX |
---|
132 | ## try to eliminate circular references - this may be overkill |
---|
133 | #if LazyWrapper is not None: |
---|
134 | # context._compiler = None |
---|
135 | # context.contexts = None |
---|
136 | # context.repeat_vars = None |
---|
137 | # if PLONE25: |
---|
138 | # items = context.global_vars.items() |
---|
139 | # else: |
---|
140 | # items = context.vars.items() |
---|
141 | # for k,v in items: |
---|
142 | # if isinstance(v, LazyWrapper): |
---|
143 | # v._expr = None |
---|
144 | # v._econtext = None |
---|
145 | # v._result = None |
---|
146 | # if PLONE25: |
---|
147 | # if context.vars: |
---|
148 | # while len(context.vars): |
---|
149 | # context.vars._pop() |
---|
150 | # context.global_vars.clear() |
---|
151 | # context.global_vars = None |
---|
152 | # context.local_vars.clear() |
---|
153 | # context.local_vars = None |
---|
154 | # else: |
---|
155 | # context.vars.clear() |
---|
156 | # context.vars = None |
---|
157 | # context._scope_stack = None |
---|
158 | |
---|
159 | result = output.getvalue() |
---|
160 | if not source: |
---|
161 | _setCacheHeaders(self, extra_context, rule, header_set, expr_context) |
---|
162 | return result |
---|
163 | |
---|
164 | |
---|
165 | def run(): |
---|
166 | log('Applying CMF patches...') |
---|
167 | from Products.PageTemplates.PageTemplate import PageTemplate |
---|
168 | wrap_method(PageTemplate, 'pt_render', PT_pt_render, '__CacheSetup_PageTemplate_%s__') |
---|
169 | from Products.CMFCore.FSPageTemplate import FSPageTemplate |
---|
170 | wrap_method(FSPageTemplate, 'pt_render', FSPT_pt_render, '__CacheSetup_FSPageTemplate_%s__') |
---|
171 | log('CMF Patches applied.') |
---|
172 | |
---|