From 3f81fe9ab5e7eeed0c9a7a756ec6b87f48626988 Mon Sep 17 00:00:00 2001 From: Ramon Bartl Date: Thu, 12 Dec 2019 11:33:53 +0100 Subject: [PATCH 1/5] Support Multiple Catalogs for Dexterity Contents --- .../catalog/catalog_multiplex_processor.py | 86 +++++++++++++++++++ bika/lims/catalog/configure.zcml | 21 +++++ bika/lims/config.py | 8 ++ bika/lims/configure.zcml | 9 +- bika/lims/interfaces/__init__.py | 5 ++ setup.py | 3 + 6 files changed, 131 insertions(+), 1 deletion(-) create mode 100644 bika/lims/catalog/catalog_multiplex_processor.py create mode 100644 bika/lims/catalog/configure.zcml diff --git a/bika/lims/catalog/catalog_multiplex_processor.py b/bika/lims/catalog/catalog_multiplex_processor.py new file mode 100644 index 0000000000..c3a98d1435 --- /dev/null +++ b/bika/lims/catalog/catalog_multiplex_processor.py @@ -0,0 +1,86 @@ +# -*- 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) + catalog.catalog_object(obj, url, idxs=list(indexes)) + + def reindex(self, obj, attributes=None): + self.index(obj, attributes) + + def unindex(self, obj): + if aq_base(obj).__class__.__name__ == "PathWrapper": + # Could be a PathWrapper object from collective.indexing. + obj = obj.context + + if IMultiCatalogBehavior(obj, None) is None: + return + + catalogs = self.get_catalogs_for(obj) + url = api.get_path(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..2860112996 --- /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': [ From a3411cd9b4b0fa8c6409a23f941c6c9b85cbac81 Mon Sep 17 00:00:00 2001 From: Ramon Bartl Date: Thu, 12 Dec 2019 11:43:23 +0100 Subject: [PATCH 2/5] Changelog updated --- CHANGES.rst | 1 + 1 file changed, 1 insertion(+) 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 From b7a3b9b332a93b8f242233619fb5cd150149244e Mon Sep 17 00:00:00 2001 From: Ramon Bartl Date: Fri, 13 Dec 2019 16:49:39 +0100 Subject: [PATCH 3/5] Fixed typo --- bika/lims/catalog/configure.zcml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bika/lims/catalog/configure.zcml b/bika/lims/catalog/configure.zcml index 2860112996..2b03094dad 100644 --- a/bika/lims/catalog/configure.zcml +++ b/bika/lims/catalog/configure.zcml @@ -15,7 +15,7 @@ zcml:condition="installed collective.indexing" factory=".catalog_multiplex_processor.CatalogMultiplexProcessor" provides="collective.indexing.indexer.IPortalCatalogQueueProcessor" - name="catalogmulitplex" + name="catalogmultiplex" /> From 0eee80c8b2564bd7c8c272265845e712173342ec Mon Sep 17 00:00:00 2001 From: Ramon Bartl Date: Fri, 13 Dec 2019 16:49:51 +0100 Subject: [PATCH 4/5] Fixed unindexing path --- bika/lims/catalog/catalog_multiplex_processor.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/bika/lims/catalog/catalog_multiplex_processor.py b/bika/lims/catalog/catalog_multiplex_processor.py index c3a98d1435..3df28d149c 100644 --- a/bika/lims/catalog/catalog_multiplex_processor.py +++ b/bika/lims/catalog/catalog_multiplex_processor.py @@ -59,15 +59,17 @@ 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 IMultiCatalogBehavior(obj, None) is None: + if not self.supports_multi_catalogs(obj): return catalogs = self.get_catalogs_for(obj) - url = api.get_path(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: From 108646eebee1cb932506fb8219d9d94953145e49 Mon Sep 17 00:00:00 2001 From: Ramon Bartl Date: Fri, 13 Dec 2019 19:23:26 +0100 Subject: [PATCH 5/5] Skip reindexing if no indexes match with the current catalog --- bika/lims/catalog/catalog_multiplex_processor.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/bika/lims/catalog/catalog_multiplex_processor.py b/bika/lims/catalog/catalog_multiplex_processor.py index 3df28d149c..2cd3cf4a24 100644 --- a/bika/lims/catalog/catalog_multiplex_processor.py +++ b/bika/lims/catalog/catalog_multiplex_processor.py @@ -53,6 +53,10 @@ def index(self, obj, attributes=None): # 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):