Updated views management
authorThierry Florac <thierry.florac@onf.fr>
Tue, 08 Jan 2019 14:02:06 +0100
changeset 1217 ac40004d7c73
parent 1216 30602138e7f7
child 1218 9f8b56eeb149
Updated views management
src/pyams_content/shared/view/__init__.py
src/pyams_content/shared/view/interfaces.py
src/pyams_content/shared/view/merge.py
src/pyams_content/shared/view/reference.py
src/pyams_content/shared/view/theme.py
--- a/src/pyams_content/shared/view/__init__.py	Mon Jan 07 11:36:09 2019 +0100
+++ b/src/pyams_content/shared/view/__init__.py	Tue Jan 08 14:02:06 2019 +0100
@@ -9,6 +9,9 @@
 # WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
 # FOR A PARTICULAR PURPOSE.
 #
+from copy import deepcopy
+
+from jedi.evaluate.helpers import deep_ast_copy
 
 __docformat__ = 'restructuredtext'
 
@@ -112,7 +115,7 @@
 
     def get_results(self, context, sort_index=None, reverse=None, limit=None,
                     start=0, length=999, ignore_cache=False, get_count=False, request=None):
-        results = _MARKER
+        results, count = _MARKER, 0
         if not ignore_cache:
             # check for cache
             views_cache = get_cache(VIEWS_CACHE_REGION, VIEWS_CACHE_NAME)
@@ -129,11 +132,13 @@
         # Execute query
         if results is _MARKER:
             registry = get_current_registry()
+            # Look for Elasticsearch query adapter, if available...
             adapter = registry.queryAdapter(self, IViewQuery, name='es')
             if adapter is None:
                 adapter = registry.getAdapter(self, IViewQuery)
             if not sort_index:
                 sort_index = self.order_by
+            # Get query results
             results, count = adapter.get_results(context,
                                                  sort_index,
                                                  reverse if reverse is not None else self.reversed_order,
@@ -189,25 +194,27 @@
             for new_params in adapter.get_params(context, request):
                 if isinstance(new_params, tuple):
                     new_params, do_search = new_params
-                if new_params:
+                if new_params is None:
+                    return None
+                else:
                     params &= new_params
             if not do_search:
                 break
         # activate search
         if do_search:
-            params &= Gt(catalog['push_end_date'], now)
+            filters = Gt(catalog['push_end_date'], now)
             # check content path
             content_path = view.get_content_path(context)
             if content_path is not None:
-                params &= Eq(catalog['parents'], content_path)
+                filters &= Eq(catalog['parents'], content_path)
             # check content types
             content_types = view.get_content_types(context)
             if content_types:
-                params &= Any(catalog['content_type'], content_types)
+                filters &= Any(catalog['content_type'], content_types)
             # check data types
             data_types = view.get_data_types(context)
             if data_types:
-                params &= Any(catalog['data_type'], data_types)
+                filters &= Any(catalog['data_type'], data_types)
         return params
 
     def get_results(self, context, sort_index, reverse, limit, request=None):
@@ -215,14 +222,18 @@
         catalog = get_utility(ICatalog)
         registry = get_current_registry()
         params = self.get_params(context, request)
-        if (not sort_index) or (sort_index == RELEVANCE_ORDER):
-            sort_index = None
-        query = CatalogQuery(catalog).query(params,
-                                            sort_index=sort_index,
-                                            reverse=reverse,
-                                            limit=limit)
-        total_count = query[0]
-        items = CatalogResultSet(query)
+        if params is None:
+            items = CatalogResultSet([])
+            total_count = 0
+        else:
+            if (not sort_index) or (sort_index == RELEVANCE_ORDER):
+                sort_index = None
+            query = CatalogQuery(catalog).query(params,
+                                                sort_index=sort_index,
+                                                reverse=reverse,
+                                                limit=limit)
+            total_count = query[0]
+            items = CatalogResultSet(query)
         for name, adapter in sorted(registry.getAdapters((view,), IViewQueryFilterExtension),
                                     key=lambda x: x[1].weight):
             items = adapter.filter(context, items, request)
--- a/src/pyams_content/shared/view/interfaces.py	Mon Jan 07 11:36:09 2019 +0100
+++ b/src/pyams_content/shared/view/interfaces.py	Tue Jan 08 14:02:06 2019 +0100
@@ -168,7 +168,13 @@
     """View query extension interface"""
 
     def get_params(self, context, request=None):
-        """Add params to catalog query"""
+        """Add params to catalog query
+
+        This method may return an iterator.
+        If defined settings are such that no result can be found (for example, if the view is
+        defined to use context themes but context doesn't have any), method can yield a "None"
+        value which will cancel query execution.
+        """
 
 
 class IViewQueryEsParamsExtension(IViewQueryExtension):
--- a/src/pyams_content/shared/view/merge.py	Mon Jan 07 11:36:09 2019 +0100
+++ b/src/pyams_content/shared/view/merge.py	Tue Jan 08 14:02:06 2019 +0100
@@ -12,23 +12,19 @@
 
 __docformat__ = 'restructuredtext'
 
-
-# import standard library
 from heapq import merge
-from random import shuffle
 from itertools import chain, zip_longest
+from random import shuffle
 
-# import interfaces
-from pyams_content.shared.view.interfaces import VIEWS_MERGERS_VOCABULARY, IViewsMerger, CREATION_DATE_ORDER, \
-    UPDATE_DATE_ORDER, PUBLICATION_DATE_ORDER, FIRSTPUBLICATION_DATE_ORDER
-from pyams_workflow.interfaces import IWorkflowPublicationInfo
+from zope.componentvocabulary.vocabulary import UtilityTerm, UtilityVocabulary
 from zope.dublincore.interfaces import IZopeDublinCore
 
-# import packages
+from pyams_content.shared.view.interfaces import CREATION_DATE_ORDER, FIRSTPUBLICATION_DATE_ORDER, IViewsMerger, \
+    PUBLICATION_DATE_ORDER, UPDATE_DATE_ORDER, VIEWS_MERGERS_VOCABULARY
 from pyams_utils.registry import utility_config
 from pyams_utils.request import check_request
 from pyams_utils.vocabulary import vocabulary_config
-from zope.componentvocabulary.vocabulary import UtilityVocabulary, UtilityTerm
+from pyams_workflow.interfaces import IWorkflowPublicationInfo
 
 from pyams_content import _
 
--- a/src/pyams_content/shared/view/reference.py	Mon Jan 07 11:36:09 2019 +0100
+++ b/src/pyams_content/shared/view/reference.py	Tue Jan 08 14:02:06 2019 +0100
@@ -47,7 +47,7 @@
         refs = []
         if self.select_context_references:
             references = IInternalReferencesList(context, None)
-            if references is not None:
+            if (references is not None) and references.references:
                 refs.extend(references.references)
         if self.references:
             refs.extend(self.references)
@@ -70,31 +70,44 @@
 
     def get_params(self, context, request=None):
         settings = IViewInternalReferencesSettings(self.context)
-        catalog = get_utility(ICatalog)
-        # check view settings
-        if settings.exclude_context:
-            sequence = ISequentialIdInfo(context, None)
-            if sequence is not None:
-                oid = sequence.hex_oid
-                yield NotEq(catalog['oid'], oid)
         # check view references mode
         if settings.references_mode == ONLY_REFERENCE_MODE:
-            yield Any(catalog['oid'], settings.references), False
+            # references are retrieved by query filter extension, so no params are required!
+            yield None
+        else:
+            # check view settings
+            if settings.exclude_context:
+                sequence = ISequentialIdInfo(context, None)
+                if sequence is not None:
+                    oid = sequence.hex_oid
+                    catalog = get_utility(ICatalog)
+                    yield NotEq(catalog['oid'], oid)
 
 
 @adapter_config(name='references', context=IWfView, provides=IViewQueryFilterExtension)
 class ViewInternalReferencesQueryFilterExtension(ContextAdapter):
-    """View internal references filter extension"""
+    """View internal references filter extension
+
+    If internal references are selected, these references are forced.
+    """
 
     weight = 999
 
     def filter(self, context, items, request=None):
         settings = IViewInternalReferencesSettings(self.context)
-        if not settings.references:
+        references = settings.get_references(context)
+        if not references:
             return items
-        if (not items) or (settings.references_mode == ALWAYS_REFERENCE_MODE):
+        excluded_oid = None
+        if settings.exclude_context:
+            sequence = ISequentialIdInfo(context, None)
+            if sequence is not None:
+                excluded_oid = sequence.hex_oid
+        if (not items) or (settings.references_mode in (ALWAYS_REFERENCE_MODE, ONLY_REFERENCE_MODE)):
             catalog = get_utility(ICatalog)
-            for reference in settings.references:
+            for reference in reversed(references):
+                if reference == excluded_oid:
+                    continue
                 params = Eq(catalog['oid'], reference) & \
                          Any(catalog['workflow_state'], VISIBLE_STATES)
                 items.prepend(CatalogResultSet(CatalogQuery(catalog).query(params)))
--- a/src/pyams_content/shared/view/theme.py	Mon Jan 07 11:36:09 2019 +0100
+++ b/src/pyams_content/shared/view/theme.py	Tue Jan 08 14:02:06 2019 +0100
@@ -82,6 +82,8 @@
         tags = settings.get_tags_index(context)
         if tags:
             yield Any(catalog['tags'], tags)
+        elif settings.select_context_tags:
+            yield None
 
 
 @adapter_config(name='tags', context=SearchFolderQuery, provides=IViewUserQuery)
@@ -156,6 +158,8 @@
         themes = settings.get_themes_index(context)
         if themes:
             yield Any(catalog['themes'], themes)
+        elif settings.select_context_themes:
+            yield None
 
 
 #
@@ -209,3 +213,5 @@
         collections = settings.get_collections_index(context)
         if collections:
             yield Any(catalog['collections'], collections)
+        elif settings.select_context_collections:
+            yield None