Back to index

plone3  3.1.7
manager.py
Go to the documentation of this file.
00001 from zope.interface import implements
00002 from zope.component import getUtility, getAdapters
00003 from zope.component import getMultiAdapter, queryMultiAdapter
00004 
00005 from zope.viewlet.interfaces import IViewlet
00006 from zope.contentprovider.interfaces import IContentProvider
00007 
00008 from zope.interface import providedBy
00009 
00010 from Acquisition import aq_base
00011 from AccessControl.ZopeGuards import guarded_hasattr
00012 from Products.Five import BrowserView
00013 from Products.Five.browser.pagetemplatefile import ViewPageTemplateFile
00014 
00015 from plone.app.viewletmanager.interfaces import IViewletSettingsStorage
00016 from plone.app.viewletmanager.interfaces import IViewletManagementView
00017 
00018 from cgi import parse_qs
00019 from urllib import urlencode
00020 
00021 
00022 class BaseOrderedViewletManager(object):
00023     def filter(self, viewlets):
00024         """Filter the viewlets.
00025     
00026         ``viewlets`` is a list of tuples of the form (name, viewlet).
00027 
00028         This filters the viewlets just like Five, but also filters out
00029         viewlets by name from the local utility which implements the
00030         IViewletSettingsStorage interface.
00031         """
00032         storage = getUtility(IViewletSettingsStorage)
00033         skinname = self.context.getCurrentSkinName()
00034         hidden = frozenset(storage.getHidden(self.__name__, skinname))
00035         results = []
00036         # Only return visible viewlets accessible to the principal
00037         # We need to wrap each viewlet in its context to make sure that
00038         # the object has a real context from which to determine owner
00039         # security.
00040         # Copied from Five
00041         for name, viewlet in viewlets:
00042             viewlet = viewlet.__of__(viewlet.context)
00043             if name not in hidden and guarded_hasattr(viewlet, 'render'):
00044                 results.append((name, viewlet))
00045         return results
00046 
00047     def sort(self, viewlets):
00048         """Sort the viewlets.
00049 
00050         ``viewlets`` is a list of tuples of the form (name, viewlet).
00051 
00052         This sorts the viewlets by the order looked up from the local utility
00053         which implements the IViewletSettingsStorage interface. The remaining
00054         ones are sorted just like Five does it.
00055         """
00056 
00057         storage = getUtility(IViewletSettingsStorage)
00058         skinname = self.context.getCurrentSkinName()
00059         order_by_name = storage.getOrder(self.__name__, skinname)
00060         # first get the known ones
00061         name_map = dict(viewlets)
00062         result = []
00063         for name in order_by_name:
00064             if name in name_map:
00065                 result.append((name, name_map[name]))
00066                 del name_map[name]
00067 
00068         # then sort the remaining ones
00069         # Copied from Five
00070         remaining = sorted(name_map.items(),
00071                            lambda x, y: cmp(aq_base(x[1]), aq_base(y[1])))
00072 
00073         # return both together
00074         return result + remaining
00075 
00076     def render(self):
00077         if self.template:
00078             return self.template(viewlets=self.viewlets)
00079         else:
00080             return u'\n'.join([viewlet.render() for viewlet in self.viewlets])
00081 
00082 
00083 class OrderedViewletManager(BaseOrderedViewletManager):
00084     manager_template = ViewPageTemplateFile('manage-viewletmanager.pt')
00085 
00086     def render(self):
00087         """See zope.contentprovider.interfaces.IContentProvider"""
00088 
00089         # check whether we are in the manager view
00090         is_managing = False
00091         parent = getattr(self, '__parent__', None)
00092         while parent is not None:
00093             if IViewletManagementView.providedBy(parent):
00094                 is_managing = True
00095                 break
00096             parent = getattr(parent, '__parent__', None)
00097 
00098         if is_managing:
00099             # if we are in the managing view, then fetch all viewlets again
00100             viewlets = getAdapters(
00101                 (self.context, self.request, self.__parent__, self),
00102                 IViewlet)
00103 
00104             # sort them first
00105             viewlets = self.sort(viewlets)
00106 
00107             storage = getUtility(IViewletSettingsStorage)
00108             skinname = self.context.getCurrentSkinName()
00109             hidden = frozenset(storage.getHidden(self.__name__, skinname))
00110 
00111             # then render the ones which are accessible
00112             base_url = str(getMultiAdapter((self.context, self.request),
00113                            name='absolute_url'))
00114             query_tmpl = "%s/@@manage-viewlets?%%s" % base_url
00115             results = []
00116             for index, (name, viewlet) in enumerate(viewlets):
00117                 viewlet = viewlet.__of__(viewlet.context)
00118                 viewlet_id = "%s:%s" % (self.__name__, name)
00119                 options = {'index': index,
00120                            'name': name}
00121                 if guarded_hasattr(viewlet, 'render'):
00122                     viewlet.update()
00123                     options['content'] = viewlet.render()
00124                 else:
00125                     options['content'] = u""
00126                 if name in hidden:
00127                     options['hidden'] = True
00128                     query = {'show': viewlet_id}
00129                     options['show_url'] = query_tmpl % urlencode(query)
00130                 else:
00131                     options['hidden'] = False
00132                     query = {'hide': viewlet_id}
00133                     options['hide_url'] = query_tmpl % urlencode(query)
00134                 if index > 0:
00135                     prev_viewlet = viewlets[index-1][0]
00136                     query = {'move_above': "%s;%s" % (viewlet_id, prev_viewlet)}
00137                     options['up_url'] = query_tmpl % urlencode(query)
00138                 if index < (len(viewlets) - 1):
00139                     next_viewlet = viewlets[index+1][0]
00140                     query = {'move_below': "%s;%s" % (viewlet_id, next_viewlet)}
00141                     options['down_url'] = query_tmpl % urlencode(query)
00142                 results.append(options)
00143 
00144             self.name = self.__name__
00145             self.interface = list(providedBy(self).flattened())[0].__identifier__
00146             
00147             # and output them
00148             return self.manager_template(viewlets=results)
00149         # the rest is standard behaviour from zope.viewlet
00150         else:
00151             return BaseOrderedViewletManager.render(self)
00152 
00153 
00154 class ManageViewlets(BrowserView):
00155     implements(IViewletManagementView)
00156 
00157     def show(self, manager, viewlet):
00158         storage = getUtility(IViewletSettingsStorage)
00159         skinname = self.context.getCurrentSkinName()
00160         hidden = storage.getHidden(manager, skinname)
00161         if viewlet in hidden:
00162             hidden = tuple(x for x in hidden if x != viewlet)
00163             storage.setHidden(manager, skinname, hidden)
00164 
00165     def hide(self, manager, viewlet):
00166         storage = getUtility(IViewletSettingsStorage)
00167         skinname = self.context.getCurrentSkinName()
00168         hidden = storage.getHidden(manager, skinname)
00169         if viewlet not in hidden:
00170             hidden = hidden + (viewlet,)
00171             storage.setHidden(manager, skinname, hidden)
00172 
00173     def _getOrder(self, manager_name):
00174         storage = getUtility(IViewletSettingsStorage)
00175         skinname = self.context.getCurrentSkinName()
00176         manager = queryMultiAdapter(
00177             (self.context, self.request, self), IContentProvider, manager_name)
00178         viewlets = getAdapters(
00179             (manager.context, manager.request, manager.__parent__, manager),
00180             IViewlet)
00181         order_by_name = storage.getOrder(manager_name, skinname)
00182         # first get the known ones
00183         name_map = dict(viewlets)
00184         result = []
00185         for name in order_by_name:
00186             if name in name_map:
00187                 result.append((name, name_map[name]))
00188                 del name_map[name]
00189 
00190         # then sort the remaining ones
00191         # Copied from Five
00192         remaining = sorted(name_map.items(),
00193                            lambda x, y: cmp(aq_base(x[1]), aq_base(y[1])))
00194 
00195         return [x[0] for x in result + remaining]
00196 
00197     def moveAbove(self, manager, viewlet, dest):
00198         storage = getUtility(IViewletSettingsStorage)
00199         skinname = self.context.getCurrentSkinName()
00200         order = self._getOrder(manager)
00201         viewlet_index = order.index(viewlet)
00202         del order[viewlet_index]
00203         dest_index = order.index(dest)
00204         order.insert(dest_index, viewlet)
00205         storage.setOrder(manager, skinname, order)
00206 
00207     def moveBelow(self, manager, viewlet, dest):
00208         storage = getUtility(IViewletSettingsStorage)
00209         skinname = self.context.getCurrentSkinName()
00210         order = self._getOrder(manager)
00211         viewlet_index = order.index(viewlet)
00212         del order[viewlet_index]
00213         dest_index = order.index(dest)
00214         order.insert(dest_index+1, viewlet)
00215         storage.setOrder(manager, skinname, order)
00216 
00217     def __call__(self):
00218         base_url = "%s/@@manage-viewlets" % str(
00219                        getMultiAdapter((self.context, self.request),
00220                        name='absolute_url')
00221                    )
00222         qs = self.request.get('QUERY_STRING', None)
00223         if qs is not None:
00224             query = parse_qs(qs)
00225             if 'show' in query:
00226                 for name in query['show']:
00227                     manager, viewlet = name.split(':')
00228                     self.show(manager, viewlet)
00229                     self.request.response.redirect(base_url)
00230                     return ''
00231             if 'hide' in query:
00232                 for name in query['hide']:
00233                     manager, viewlet = name.split(':')
00234                     self.hide(manager, viewlet)
00235                     self.request.response.redirect(base_url)
00236                     return ''
00237             if 'move_above' in query:
00238                 for name in query['move_above']:
00239                     manager, viewlets = name.split(':')
00240                     viewlet, dest = viewlets.split(';')
00241                     self.moveAbove(manager, viewlet, dest)
00242                     self.request.response.redirect(base_url)
00243                     return ''
00244             if 'move_below' in query:
00245                 for name in query['move_below']:
00246                     manager, viewlets = name.split(':')
00247                     viewlet, dest = viewlets.split(';')
00248                     self.moveBelow(manager, viewlet, dest)
00249                     self.request.response.redirect(base_url)
00250                     return ''
00251         return self.index()