diff --git a/CHANGES.rst b/CHANGES.rst index eb32a383bf..3e6aad5f61 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -7,6 +7,7 @@ Changelog **Added** +- #1489 Support Multiple Catalogs for Dexterity Contents - #1481 Filter Templates field when Sample Type is selected in Sample Add form - #1483 Added Accredited symbol in Analyses listings - #1466 Support for "readonly" and "hidden" visibility modes in ReferenceWidget diff --git a/bika/lims/catalog/catalog_multiplex_processor.py b/bika/lims/catalog/catalog_multiplex_processor.py new file mode 100644 index 0000000000..2cd3cf4a24 --- /dev/null +++ b/bika/lims/catalog/catalog_multiplex_processor.py @@ -0,0 +1,92 @@ +# -*- coding: utf-8 -*- + +from Acquisition import aq_base +from bika.lims import api +from bika.lims import logger +from bika.lims.config import USE_COLLECTIVE_INDEXING +from bika.lims.interfaces import IMultiCatalogBehavior +from zope.interface import implements + +if USE_COLLECTIVE_INDEXING: + from collective.indexing.interfaces import IIndexQueueProcessor + +REQUIRED_CATALOGS = [ + "auditlog_catalog", +] + + +class CatalogMultiplexProcessor(object): + """A catalog multiplex processor + """ + if USE_COLLECTIVE_INDEXING: + implements(IIndexQueueProcessor) + + def get_catalogs_for(self, obj): + catalogs = getattr(obj, "_catalogs", []) + for rc in REQUIRED_CATALOGS: + if rc in catalogs: + continue + catalogs.append(rc) + return map(api.get_tool, catalogs) + + def supports_multi_catalogs(self, obj): + """Check if the Multi Catalog Behavior is enabled + """ + if IMultiCatalogBehavior(obj, None) is None: + return False + return True + + def index(self, obj, attributes=None): + if attributes is None: + attributes = [] + + if not self.supports_multi_catalogs(obj): + return + + catalogs = self.get_catalogs_for(obj) + url = api.get_path(obj) + + for catalog in catalogs: + logger.info( + "CatalogMultiplexProcessor::indexObject:catalog={} url={}" + .format(catalog.id, url)) + # We want the intersection of the catalogs idxs + # and the incoming list. + indexes = set(catalog.indexes()).intersection(attributes) + # Skip reindexing if no indexes match + if attributes and not indexes: + continue + # recatalog the object + catalog.catalog_object(obj, url, idxs=list(indexes)) + + def reindex(self, obj, attributes=None): + self.index(obj, attributes) + + def unindex(self, obj): + wrapped_obj = obj + if aq_base(obj).__class__.__name__ == "PathWrapper": + # Could be a PathWrapper object from collective.indexing. + obj = obj.context + + if not self.supports_multi_catalogs(obj): + return + + catalogs = self.get_catalogs_for(obj) + # get the old path from the wrapped object + url = api.get_path(wrapped_obj) + + for catalog in catalogs: + if catalog._catalog.uids.get(url, None) is not None: + logger.info( + "CatalogMultiplexProcessor::unindex:catalog={} url={}" + .format(catalog.id, url)) + catalog.uncatalog_object(url) + + def begin(self): + pass + + def commit(self): + pass + + def abort(self): + pass diff --git a/bika/lims/catalog/configure.zcml b/bika/lims/catalog/configure.zcml new file mode 100644 index 0000000000..2b03094dad --- /dev/null +++ b/bika/lims/catalog/configure.zcml @@ -0,0 +1,21 @@ + + + + + + + + + + + diff --git a/bika/lims/config.py b/bika/lims/config.py index a1ab3cae30..8f3acac4dc 100644 --- a/bika/lims/config.py +++ b/bika/lims/config.py @@ -27,6 +27,14 @@ from bika.lims.utils import t # noqa from bika.lims.permissions import * # noqa +try: + import collective.indexing + collective.indexing # noqa +except ImportError: + USE_COLLECTIVE_INDEXING = False +else: + USE_COLLECTIVE_INDEXING = True + PROJECTNAME = "bika.lims" diff --git a/bika/lims/configure.zcml b/bika/lims/configure.zcml index 8ecf56822c..926cdbd5ef 100644 --- a/bika/lims/configure.zcml +++ b/bika/lims/configure.zcml @@ -26,7 +26,7 @@ - + @@ -51,6 +51,13 @@ provides="bika.lims.interfaces.IAutoGenerateID" /> + + + =1.2.0', # Python 2/3 compatibility library: https://six.readthedocs.io/ 'six', + # Needed for `IPortalCatalogQueueProcessor`, which will be included in + # `Products.CMFCore` in Plone 5. Remove after we are on Plone 5! + 'collective.indexing', ], extras_require={ 'test': [