source: products/quintagroup.catalogupdater/trunk/quintagroup/catalogupdater/utility.py @ 3602

Last change on this file since 3602 was 3602, checked in by vmaksymiv, 7 years ago

PPP fixes

  • Property svn:eol-style set to native
File size: 4.8 KB
Line 
1import logging
2import types
3import transaction
4from zope.interface import implements
5from zope.component import getMultiAdapter
6from zope.component import queryMultiAdapter
7
8from Missing import MV
9from Acquisition import aq_parent
10
11from Products.CMFCore.utils import getToolByName
12from Products.ZCatalog.Catalog import safe_callable
13
14try:
15    from plone.indexer.interfaces import IIndexableObject
16except ImportError:
17    from plone.app.content.interfaces import IIndexableObjectWrapper \
18        as _old_IIndexableObjectWrapper
19    IS_NEW = False
20else:
21    IS_NEW = True
22
23
24from quintagroup.catalogupdater.interfaces import ICatalogUpdater
25
26LOG = logging.getLogger('quintagroup.catalogupdater')
27
28
29class CatalogUpdaterUtility(object):
30
31    implements(ICatalogUpdater)
32
33    def validate(self, cat, cols):
34        # Validate catalog and column name
35        AVAIL_COLTYPES = list(types.StringTypes) + [types.ListType,
36                                                    types.TupleType]
37
38        _cat = getattr(cat, '_catalog', None)
39        if _cat is None:
40            raise AttributeError("%s - is not ZCatalog based catalog" % cat)
41
42        if not type(cols) in AVAIL_COLTYPES:
43            raise TypeError("'columns' parameter must be one of the "
44                            "following types: %s" % AVAIL_COLTYPES)
45        # Normalize columns
46        if type(cols) in types.StringTypes:
47            cols = [cols, ]
48        # Check is every column present in the catalog
49        for col in cols:
50            if not col in _cat.schema:
51                raise AttributeError("'%s' - not presented column in "
52                                     "%s catalog " % (col, cat))
53
54        return _cat, cols
55
56    def getWrappedObjectNew(self, obj, portal, catalog):
57        # Returned wrapped 'obj' object with IIndexable wrapper
58        wrapper = None
59        if not IIndexableObject.providedBy(obj):
60            # This is the CMF 2.2 compatible approach,
61            # which should be used going forward
62            wrapper = queryMultiAdapter((obj, catalog), IIndexableObject)
63        return wrapper and wrapper or obj
64
65    def getWrappedObjectOld(self, obj, portal, catalog):
66        # Returned wrapped 'obj' object with IIndexable wrapper
67        wf = getattr(self, 'portal_workflow', None)
68        # A comment for all the frustrated developers which aren't able to pin
69        # point the code which adds the review_state to the catalog. :)
70        # The review_state var and some other workflow vars are added to the
71        # indexable object wrapper throught the code in the following lines
72        if wf is not None:
73            vars = wf.getCatalogVariablesFor(obj)
74        else:
75            vars = {}
76
77        w = getMultiAdapter((obj, portal), _old_IIndexableObjectWrapper)
78        w.update(vars)
79
80        return w
81
82    def updateMetadata4All(self, catalog, columns):
83        """ Look into appropriate method of ICatalogUpdate interface
84        """
85
86        _catalog, columns = self.validate(catalog, columns)
87
88        portal = getToolByName(catalog, 'portal_url').getPortalObject()
89        root = aq_parent(portal)
90
91        data = _catalog.data
92        schema = _catalog.schema
93        paths = _catalog.paths
94        getWrappedObject = (IS_NEW and self.getWrappedObjectNew
95                            or self.getWrappedObjectOld)
96        # For subtransaction support
97        threshold = getattr(catalog, 'threshold', 10000)
98        _v_total = 0
99        _v_transaction = None
100
101        # For each catalog record update metadata
102        for rid, md in data.items():
103            # get an object
104            obj_uid = paths[rid]
105            try:
106                obj = root.unrestrictedTraverse(obj_uid)
107                obj = getWrappedObject(obj, portal, catalog)
108            except:
109                LOG.error('updateMetadata4All could not resolve '
110                          'an object from the uid %r.' % obj_uid)
111                continue
112
113            mdlist = list(md)
114            for column in columns:
115                # calculate the column value
116                attr = getattr(obj, column, MV)
117                if (attr is not MV and safe_callable(attr)):
118                    attr = attr()
119                # Update metadata value
120                indx = schema[column]
121                mdlist[indx] = attr
122
123            # Update catalog record
124            data[rid] = tuple(mdlist)
125
126            # Steeled from ZCatalog
127            if threshold is not None:
128                # figure out whether or not to commit a subtransaction.
129                t = id(transaction.get())
130                if t != _v_transaction:
131                    _v_total = 0
132                _v_transaction = t
133                _v_total = _v_total + 1
134                if _v_total > threshold:
135                    transaction.savepoint(optimistic=True)
136                    catalog._p_jar.cacheGC()
137                    _v_total = 0
138                    LOG.info('commiting subtransaction')
Note: See TracBrowser for help on using the repository browser.