src/pyams_content/shared/view/__init__.py
changeset 92 3facc843c06f
parent 81 3e37d4dd8e3b
child 95 83d6b58ada5f
--- a/src/pyams_content/shared/view/__init__.py	Tue Jun 27 11:47:34 2017 +0200
+++ b/src/pyams_content/shared/view/__init__.py	Tue Jun 27 11:49:01 2017 +0200
@@ -10,22 +10,38 @@
 # FOR A PARTICULAR PURPOSE.
 #
 
-
 __docformat__ = 'restructuredtext'
 
 
 # import standard library
+import logging
+logger = logging.getLogger("PyAMS (content)")
 
 # import interfaces
-from pyams_content.component.links.interfaces import ILinkContainerTarget
-from pyams_content.shared.view.interfaces import IWfView, IView, VIEW_CONTENT_TYPE, VIEW_CONTENT_NAME
+from hypatia.interfaces import ICatalog
+from pyams_content.shared.view.interfaces import IView, IWfView, IViewQuery, IViewQueryParamsExtension, \
+    IViewQueryFilterExtension, VIEW_CONTENT_TYPE, VIEW_CONTENT_NAME
+from zope.intid.interfaces import IIntIds
 
 # import packages
+from hypatia.catalog import CatalogQuery
+from hypatia.query import Any
+from pyams_cache.beaker import get_cache
+from pyams_catalog.query import CatalogResultSet, or_
 from pyams_content.shared.common import WfSharedContent, register_content_type, SharedContent
+from pyams_utils.adapter import adapter_config, ContextAdapter
+from pyams_utils.list import unique
+from pyams_utils.registry import get_utility
+from pyams_workflow.interfaces import IWorkflow
+from pyramid.threadlocal import get_current_registry
 from zope.interface import implementer
 from zope.schema.fieldproperty import FieldProperty
 
 
+VIEWS_CACHE_NAME = 'PyAMS::view'
+VIEWS_CACHE_KEY = 'view_{view}.context_{context}'
+
+
 @implementer(IWfView)
 class WfView(WfSharedContent):
     """Base view"""
@@ -35,7 +51,27 @@
 
     selected_content_types = FieldProperty(IWfView['selected_content_types'])
     order_by = FieldProperty(IWfView['order_by'])
-    reversed_order  =FieldProperty(IWfView['reversed_order'])
+    reversed_order = FieldProperty(IWfView['reversed_order'])
+
+    def get_results(self, context, limit=None):
+        intids = get_utility(IIntIds)
+        views_cache = get_cache('default', VIEWS_CACHE_NAME)
+        cache_key = VIEWS_CACHE_KEY.format(view=intids.queryId(self),
+                                           context=intids.queryId(context))
+        try:
+            results = views_cache.get_value(cache_key)
+        except KeyError:
+            registry = get_current_registry()
+            adapter = registry.queryAdapter(self, IViewQuery, name='es')
+            if adapter is None:
+                adapter = registry.getAdapter(self, IViewQuery)
+            results = adapter.get_results(context)
+            views_cache.set_value(cache_key, [intids.queryId(item) for item in results])
+            logger.debug("Storing view items to cache key {0}".format(cache_key))
+        else:
+            results = CatalogResultSet(results)
+            logger.debug("Retrieving view items from cache key {0}".format(cache_key))
+        return results
 
 register_content_type(WfView)
 
@@ -45,3 +81,38 @@
     """Workflow managed view class"""
 
     content_class = WfView
+
+
+@adapter_config(context=IWfView, provides=IViewQuery)
+class ViewQuery(ContextAdapter):
+    """View query"""
+
+    def get_es_params(self, context):
+        view = self.context
+        catalog = get_utility(ICatalog)
+        registry = get_current_registry()
+        params = Any(catalog['content_type'], view.selected_content_types)
+        wf_params = None
+        for workflow in registry.getAllUtilitiesRegisteredFor(IWorkflow):
+            wf_params = or_(wf_params, Any(catalog['workflow_state'], workflow.published_states))
+        params &= wf_params
+        for name, adapter in sorted(registry.getAdapters((view,), IViewQueryParamsExtension),
+                                    key=lambda x: x[1].weight):
+            new_params = adapter.get_params(context)
+            if new_params:
+                params &= new_params
+        return params
+
+    def get_results(self, context, limit=None):
+        view = self.context
+        catalog = get_utility(ICatalog)
+        registry = get_current_registry()
+        params = self.get_es_params(context)
+        items = CatalogResultSet(CatalogQuery(catalog).query(params,
+                                                             sort_index=view.order_by,
+                                                             reverse=view.reversed_order,
+                                                             limit=limit))
+        for name, adapter in sorted(registry.getAdapters((view,), IViewQueryFilterExtension),
+                                    key=lambda x: x[1].weight):
+            items = adapter.filter(context, items)
+        return unique(items)