Back to index

plone3  3.1.7
retriever.py
Go to the documentation of this file.
00001 from zope.interface import implements, Interface
00002 from zope.component import adapts
00003 from zope.annotation.interfaces import IAnnotations
00004 
00005 from plone.portlets.interfaces import IPortletContext
00006 from plone.portlets.interfaces import ILocalPortletAssignable
00007 from plone.portlets.interfaces import IPortletManager
00008 from plone.portlets.interfaces import IPlacelessPortletManager
00009 from plone.portlets.interfaces import IPortletRetriever
00010 
00011 from plone.portlets.constants import CONTEXT_ASSIGNMENT_KEY
00012 from plone.portlets.constants import CONTEXT_BLACKLIST_STATUS_KEY
00013 
00014 from plone.portlets.constants import CONTEXT_CATEGORY
00015 
00016 class PortletRetriever(object):
00017     """The default portlet retriever.
00018 
00019     This will examine the context and its parents for contextual portlets,
00020     provided they provide ILocalPortletAssignable.
00021     """
00022 
00023     implements(IPortletRetriever)
00024     adapts(Interface, IPortletManager)
00025 
00026     def __init__(self, context, storage):
00027         self.context = context
00028         self.storage = storage
00029 
00030     def getPortlets(self):
00031         """Work out which portlets to display, returning a list of dicts
00032         describing assignments to render.
00033         """
00034         
00035         pcontext = IPortletContext(self.context, None)
00036         if pcontext is None:
00037             return []
00038             
00039         # Holds a list of (category, key, assignment).
00040         categories = [] 
00041         
00042         # Keeps track of the blacklisting status for global categores 
00043         # (user, group, content type). The status is either True (blocked)
00044         # or False (not blocked).
00045         blacklisted = {}
00046                 
00047         # This is the name of the manager (column) we're rendering
00048         manager = self.storage.__name__
00049         
00050         # 1. Fetch blacklisting status for each global category
00051 
00052         # First, find out which categories we will need to determine
00053         # blacklist status for
00054         
00055         for category, key in pcontext.globalPortletCategories(False):
00056             blacklisted[category] = None
00057         
00058         # Then walk the content hierarchy to find out what blacklist status
00059         # was assigned. Note that the blacklist is tri-state; if it's None it
00060         # means no assertion has been made (i.e. the category has neither been
00061         # whitelisted or blacklisted by this object or any parent). The first
00062         # item to give either a blacklisted (True) or whitelisted (False)
00063         # value for a given item will set the appropriate value. Parents of
00064         # this item that also set a black- or white-list value will then be
00065         # ignored.
00066 
00067         # Whilst walking the hierarchy, we also collect parent portlets, 
00068         # until we hit the first block.
00069 
00070         current = self.context
00071         currentpc = pcontext
00072         blacklistFetched = set()
00073         parentsBlocked = False
00074         
00075         while current is not None and currentpc is not None:
00076             assignable = ILocalPortletAssignable(current, None)
00077             if assignable is not None:
00078                 annotations = IAnnotations(assignable)
00079                 
00080                 if not parentsBlocked:
00081                     local = annotations.get(CONTEXT_ASSIGNMENT_KEY, None)
00082                     if local is not None:
00083                         localManager = local.get(manager, None)
00084                         if localManager is not None:
00085                             categories.extend([(CONTEXT_CATEGORY, currentpc.uid, a) for a in localManager.values()])
00086 
00087                 blacklistStatus = annotations.get(CONTEXT_BLACKLIST_STATUS_KEY, {}).get(manager, None)
00088                 if blacklistStatus is not None:
00089                     for cat, status in blacklistStatus.items():
00090                         if cat == CONTEXT_CATEGORY:
00091                             if not parentsBlocked and status == True:
00092                                 parentsBlocked = True
00093                         else: # global portlet categories
00094                             if blacklisted.get(cat, False) is None:
00095                                 blacklisted[cat] = status
00096                             if status is not None:
00097                                 blacklistFetched.add(cat)
00098                                 
00099             # We can abort if parents are blocked and we've fetched all
00100             # blacklist statuses
00101             
00102             if parentsBlocked and len(blacklistFetched) == len(blacklisted):
00103                 break
00104                     
00105             # Check the parent - if there is no parent, we will stop
00106             current = currentpc.getParent()
00107             if current is not None:
00108                 currentpc = IPortletContext(current, None)
00109         
00110         # Get all global mappings for non-blacklisted categories
00111         
00112         for category, key in pcontext.globalPortletCategories(False):
00113             if not blacklisted[category]:
00114                 mapping = self.storage.get(category, None)
00115                 if mapping is not None:
00116                     for a in mapping.get(key, {}).values():
00117                         categories.append((category, key, a,))
00118         
00119         assignments = []
00120         for category, key, assignment in categories:
00121             assignments.append({'category'    : category,
00122                                 'key'         : key,
00123                                 'name'        : assignment.__name__,
00124                                 'assignment'  : assignment
00125                                 })
00126         return assignments
00127         
00128 class PlacelessPortletRetriever(PortletRetriever):
00129     """A placeless portlet retriever.
00130     
00131     This will aggregate user portlets, then group portlets.
00132     """
00133     
00134     implements(IPortletRetriever)
00135     adapts(Interface, IPlacelessPortletManager)
00136     
00137     def __init__(self, context, storage):
00138         self.context = context
00139         self.storage = storage
00140         
00141     def getPortlets(self):
00142         pcontext = IPortletContext(self.context, None)
00143         if pcontext is None:
00144             return []
00145             
00146         assignments = []
00147         for category, key in pcontext.globalPortletCategories(True):
00148             mapping = self.storage.get(category, None)
00149             if mapping is not None:
00150                 for assignment in mapping.get(key, {}).values():
00151                     assignments.append({'category'    : category,
00152                                         'key'         : key,
00153                                         'name'        : assignment.__name__,
00154                                         'assignment'  : assignment
00155                                         })
00156     
00157         return assignments