source: products/vendor/Products.CacheSetup/current/Products/CacheSetup/patch.py @ 3296

Last change on this file since 3296 was 3296, checked in by fenix, 12 years ago

Load Products.CacheSetup?-1.2.1 into vendor/Products.CacheSetup?/current.

  • Property svn:eol-style set to native
File size: 7.2 KB
Line 
1# Uncomment the following if you use OrderedContainer
2# Not imported directly to avoid GPL/ZPL license conflicts
3OrderedContainer = None
4#from Products.CMFPlone.PloneFolder import OrderedContainer
5
6from OFS.DTMLMethod import DTMLMethod
7from OFS.Image import Image, File
8from Acquisition import aq_base
9from DateTime import DateTime
10from Products.CMFCore.FSImage import FSImage
11from Products.CMFCore.FSFile import FSFile
12from Products.CMFCore.FSDTMLMethod import FSDTMLMethod
13from Products.CacheSetup.config import log, OFS_CACHE_ID, CACHE_TOOL_ID
14from utils import safe_hasattr
15from patch_utils import wrap_method, call
16
17try:
18    from Products.ResourceRegistries.tools.BaseRegistry import BaseRegistryTool
19    PATCH_RR = True
20except:
21    PATCH_RR = False
22
23# Goal: getting control over old-style files and images.
24
25def patch_ofs():
26    # Set default cache manager to 'DefaultCache' for images and files
27    log('Associating object with PolicyHTTPCacheManager %s...' % OFS_CACHE_ID)
28    for klass in (Image, File):
29        log('Associating %s.' % klass.__name__)
30        setattr(klass, '_Cacheable__manager_id', OFS_CACHE_ID)
31
32def fs_modified(self):
33    """What's the last modification time for this file?
34    """
35    self._updateFromFS()
36    return DateTime(self._file_mod_time)
37
38def ofs_modified(self):
39    """What's the last modification time for this object?
40    """
41    if hasattr(aq_base(self), 'bobobase_modification_time'):
42        return self.bobobase_modification_time()
43    if hasattr(aq_base(self), '_p_mtime'):
44        return DateTime(self._p_mtime)
45    return DateTime()
46
47# Goal of the following two: add a modification date to old-style
48# images and files and filesystem files and images.
49
50def patch_ofs_modified():
51    # Add 'modified' method to File/Image/DTMLMethod.
52    for klass in (Image, File, DTMLMethod):
53        if hasattr(klass, 'modified'):
54            continue
55        log('Adding "modified" method to %s.' % klass.__name__)
56        setattr(klass, 'modified', ofs_modified)
57
58def patch_fs_modified():
59    # Add 'modified' method to FSFile/FSImage/FSDTMLMethod.
60    for klass in (FSImage, FSFile, FSDTMLMethod):
61        if hasattr(klass, 'modified'):
62            continue
63        log('Adding "modified" method to %s.' % klass.__name__)
64        setattr(klass, 'modified', fs_modified)
65
66# Goal: patch indexing methods to update a counter so we know when
67# stuff is changing for ETags. Also call the purge method whenever an
68# object is indexed _or_ unindexed so that any relevant purge scripts
69# for dependent objects will be called.
70
71from Products.CMFCore.utils import getToolByName
72# this import invokes CMFSquidTool's patches
73from Products.CMFSquidTool.queue import queue
74queueObject = queue.queue
75
76# Sub-goal is to increment a counter on every catalog change.
77   
78def _purge(self, purge_squid=True):
79    if purge_squid:
80        ps = getToolByName(self, 'portal_squid', None)
81        if ps is None:
82            return
83        queueObject(self)
84    pcs = getToolByName(self, 'portal_cache_settings', None)
85    if pcs is None:
86        return
87    pcs.incrementCatalogCount()
88
89def catalog_object(self, obj, uid=None, idxs=None, update_metadata=1,
90                   pghandler=None):
91    """ZCatalog.catalog_object"""
92
93    _purge(obj)
94    try:
95        return call(self, 'catalog_object', obj, 
96                    uid, idxs, update_metadata, pghandler)
97    except:
98        # BBB for Zope2.7
99        return call(self, 'catalog_object', obj, uid, idxs,
100                    update_metadata)
101
102def uncatalog_object(self, uid):
103    """ZCatalog.uncatalog_object"""
104
105    # We need to resolve the uid if we want this to be valuable at
106    # all, doing so is potentially expensive and likely to fail. So
107    # don't purge squid.
108    _purge(self, purge_squid=False)
109    return call(self, 'uncatalog_object', uid)
110
111def moveObjectsByDelta(self, ids, delta, subset_ids=None):
112    """Move specified sub-objects by delta."""
113    _purge(self)
114    return call(self, 'moveObjectsByDelta', 
115                ids=ids, delta=delta, subset_ids=subset_ids)
116
117# Goal: signal a change in portal_css or portal_javascript by
118# incrementing the internal catalog counter (which is often used to
119# determine freshness).
120
121def cookResources(self):
122    """Cook the stored resources."""
123    parent = self.getParentNode()
124    if safe_hasattr(parent, CACHE_TOOL_ID):
125        pcs = getattr(parent, CACHE_TOOL_ID)
126        # clear out page cache
127        pcs.manage_purgePageCache()
128        # bump the catalog count to nuke (some) etag-cached content
129        pcs.incrementCatalogCount()
130    return call(self, 'cookResources')
131
132# Goal: Increment a counter every time the relationship between
133# permissions and roles changes
134
135def _incrementPermissionCount(self):
136    try:
137        pcs = getToolByName(self, 'portal_cache_settings')
138    except AttributeError:
139        return
140    pcs.incrementPermissionCount()
141
142from AccessControl.Role import RoleManager
143
144def manage_role(self, role_to_manage, permissions=[], REQUEST=None):
145    """This method is called TTW, so it needs a docstring"""
146    retval = call(self, 'manage_role', role_to_manage, permissions, REQUEST)
147    _incrementPermissionCount(self)
148    return retval
149
150def manage_acquiredPermissions(self, permissions=[], REQUEST=None):
151    """This method is called TTW, so it needs a docstring"""
152    retval = call(self, 'manage_acquiredPermissions', permissions, REQUEST)
153    _incrementPermissionCount(self)
154    return retval
155
156def manage_permission(self, permission_to_manage,
157                      roles=[], acquire=0, REQUEST=None):
158    """This method is called TTW, so it needs a docstring"""
159    retval = call(self, 'manage_permission', permission_to_manage, roles, acquire, REQUEST)
160    _incrementPermissionCount(self)
161    return retval
162
163def manage_changePermissions(self, REQUEST):
164    """This method is called TTW, so it needs a docstring"""
165    retval = call(self, 'manage_changePermissions', REQUEST)
166    _incrementPermissionCount(self)
167    return retval
168
169
170def run():
171    log('Applying patches...')
172    patch_ofs()
173    patch_ofs_modified()
174    patch_fs_modified()
175
176    from Products.CMFSquidTool.patch import unwrap_method as squidtool_unwrap_method
177    from Products.ZCatalog.ZCatalog import ZCatalog
178    from Products.Archetypes.OrderedBaseFolder import OrderedContainer as ATOrderedContainer
179    from Products.CMFCore.CMFCatalogAware import CMFCatalogAware
180    from Products.Archetypes.CatalogMultiplex import CatalogMultiplex
181    # remove CMFSquidTool's patches
182    squidtool_unwrap_method(CMFCatalogAware, 'reindexObject')
183    squidtool_unwrap_method(CatalogMultiplex, 'reindexObject')
184    # add in our own patches
185    wrap_method(ZCatalog, 'catalog_object', catalog_object)
186    wrap_method(ZCatalog, 'uncatalog_object', uncatalog_object)
187    if OrderedContainer is not None:
188        wrap_method(OrderedContainer, 'moveObjectsByDelta', moveObjectsByDelta)
189    wrap_method(ATOrderedContainer, 'moveObjectsByDelta', moveObjectsByDelta)
190    if PATCH_RR:
191        wrap_method(BaseRegistryTool, 'cookResources', cookResources)
192    wrap_method(RoleManager, 'manage_role', manage_role)
193    wrap_method(RoleManager, 'manage_acquiredPermissions', manage_acquiredPermissions)
194    wrap_method(RoleManager, 'manage_permission', manage_permission)
195    wrap_method(RoleManager, 'manage_changePermissions', manage_changePermissions)
196
197    log('Patches applied.')
Note: See TracBrowser for help on using the repository browser.