| 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 | |
|---|