root/qPloneDropDownMenu/branches/0.2/DropDownMenuTool.py

Revision 465 (checked in by piv, 2 years ago)

Plone 2.0.5 compatibility, fixed js bug

Line 
1 import os
2 from cStringIO import StringIO
3
4 from Globals import InitializeClass
5 from Globals import package_home
6 from Persistence import PersistentMapping
7 try:
8     from ZODB.PersistentList import PersistentList
9 except ImportError:
10     from persistent.list import PersistentList
11
12 from OFS.SimpleItem import SimpleItem
13 from AccessControl import ClassSecurityInfo
14
15 from Products.PageTemplates.PageTemplateFile import PageTemplateFile
16 from Products.CMFCore.utils import getToolByName, UniqueObject
17 from Products.CMFCore.Expression import Expression, createExprContext
18 from Products.CMFCore.CMFCorePermissions import ManagePortal, View
19
20 from config import UNIQUE_ID
21
22 from zLOG import LOG
23
24 _wwwdir = os.path.join(package_home(globals()), 'www')
25
26 class MenuItem(SimpleItem):
27     """ Element for displaying item in portal tab submenu """
28
29     security = ClassSecurityInfo()
30
31     def __init__(self, title, url=None):
32         """ Initialize """
33         self._title = title
34         self._url = url
35         self._menu_items = PersistentList()
36
37     security.declarePublic('getTitle')
38     def getTitle(self):
39         """ Simple accessor. """
40         return self._title
41
42     security.declareProtected(ManagePortal, 'setTitle')
43     def setTitle(self, title):
44         """ Set menu item's title """
45         self._title = title
46
47     security.declarePublic('getUrl')
48     def getUrl(self):
49         """ Simple accessor. """
50         return self._url
51
52     security.declareProtected(ManagePortal, 'setUrl')
53     def setUrl(self, url):
54         """ Set menu item's url """
55         self._url = url
56
57     security.declarePublic('listMenuItems')
58     def listMenuItems(self):
59         """Get all the menu items in subMenu. """
60         return [x.__of__(self) for x in self._menu_items] or []
61
62     security.declareProtected(ManagePortal, 'setSubMenu')
63     def setMenuItems(self, items):
64         """ Set menu item's subMenu object """
65         self._menu_items = PersistentList(items)
66
67     security.declareProtected(ManagePortal, 'addItem')
68     def addItem(self, item):
69         """ Add MenuItem to _menu_items list """
70         self._menu_items.append(item)
71
72     security.declareProtected(ManagePortal, 'deleteItem')
73     def deleteItem(self, idx):
74         """ Delete MenuItem from _menu_items list """
75         return self._menu_items.pop(idx)
76
77
78 InitializeClass(MenuItem)
79
80 class DropDownMenuTool(UniqueObject, SimpleItem):
81
82     meta_type = 'DropDownMenu Tool'
83     id = UNIQUE_ID
84     title="DropDown Menu Tool"
85
86     _submenu_mapping = PersistentMapping()
87
88     security = ClassSecurityInfo()
89
90     manage_options = ({'label' : 'Sub Menus',
91                        'action' : 'manage_editSubMenus'},) + SimpleItem.manage_options
92
93     security.declareProtected(ManagePortal, 'manage_editSubMenus')
94     manage_editSubMenus = PageTemplateFile('editSubMenus', _wwwdir)
95
96     security.declareProtected(ManagePortal, 'manage_editMenuItems')
97     manage_editMenuItems = PageTemplateFile('editMenuItems', _wwwdir)
98
99     security.declareProtected(ManagePortal, 'listPortalTabActions')
100     def listPortalTabActions(self):
101         """ Return all portal actions with 'portal_tabs' category. """
102         result = []
103         pu = getToolByName(self, 'plone_utils')
104         if hasattr(pu, 'createTopLevelTabs'):
105             pactions = getToolByName(self, 'portal_actions').listFilteredActionsFor(self)
106             tl_tabs = pu.createTopLevelTabs(pactions)
107             for act in tl_tabs:
108                 data = {'title': act['name'],
109                         'id':act['id'],
110                         'actionExpression': act['url']}
111                 result.append(data)
112         else:
113             portal = getToolByName(self, 'portal_url').getPortalObject()
114             portal_act = getToolByName(self, 'portal_actions')
115             actions = portal_act._cloneActions()
116
117             for act in actions:
118                 if act.category == 'portal_tabs':
119                     data = {'title': act.title,
120                              'id': act.id,
121                              'actionExpression': \
122                              Expression(act.getActionExpression())(createExprContext(portal, portal, portal))}
123                     result.append(data)
124         return result
125
126     security.declareProtected(ManagePortal, 'generateSubMenuMapping')
127     def generateSubMenuMapping(self):
128         """  Create top-level subMenu mapping. """
129         mapping = self._submenu_mapping
130         #for item in mapping.keys():
131             #for tab in self.listPortalTabActions():
132                 #if item == tab['title']:
133                     #present = True
134                     #break
135                 #else: present = False
136             #if not present: del mapping[item]
137         for tab in self.listPortalTabActions():
138             if tab['title'] not in mapping.keys():
139                 mapping[tab['title']] = PersistentList()
140         self._submenu_mapping = mapping
141         return self._submenu_mapping
142
143     security.declareProtected('View', 'getValueByKey')
144     def getValueByKey(self, key):
145         """  Return value from _submenu_mapping for given key """
146         try:
147             return [item.__of__(self) for item in self._submenu_mapping[key]]
148         except KeyError:
149             return None
150
151     security.declareProtected(ManagePortal, 'validateTitle')
152     def validateTitle(self, title):
153         """ Safeguard against empty (later duplicate ;) title. """
154         if not title:
155             raise ValueError, 'Please, enter title'
156         else: return 1
157
158     security.declareProtected(ManagePortal, 'getSubMenuByPath')
159     def getSubMenuByPath(self, submenu_path):
160         """ Return submenu for a given submenu_path """
161         if submenu_path in self._submenu_mapping.keys():
162             return self.getValueByKey(submenu_path)
163         else:
164             #LOG('getSubMenuByPath', 111, 'afterElseSubmenuPath', str(submenu_path))
165             return self.getMenuItemByPath(submenu_path).listMenuItems()
166
167     security.declareProtected(ManagePortal, 'getMenuItemByPath')
168     def getMenuItemByPath(self, submenu_path):
169         """ Return menuitem for a given submenu_path """
170         path = submenu_path.strip().split('/')
171         menuitem = self.getValueByKey(path[0])[int(path[1])]
172         for i in path[2:]:
173             menuitem = menuitem.listMenuItems()[int(i)]
174         return menuitem
175
176     security.declareProtected(ManagePortal, 'getBreadcrumbs')
177     def getBreadcrumbs(self, submenu_path):
178         """ Return breadcrumbs dictionary for listMenuItems form """
179         path = submenu_path.split('/')
180         result  = [{'title' : path[0],
181                     'url'   : '%s/manage_editMenuItems?submenu_path=%s'%(self.absolute_url(), path[0])},]
182         for i in range(len(path[1:])):
183             temp_path = '/'.join(path[:i+2])
184             result.append({'title' : self.getMenuItemByPath(temp_path).getTitle(),
185                             'url'   : '%s/manage_editMenuItems?submenu_path=%s'%(self.absolute_url(), temp_path)})
186         return result
187
188     #security.declareProtected(ManagePortal, 'getLevel')
189     #def getLevel(self, submenu, space, lst):
190         #if submenu != None:
191     ##        if submenu.listMenuItems() != ():
192             #space += '    '
193             #for menuitem in submenu.listMenuItems():
194                 #lst += space + menuitem.getTitle() + '  ==  ' + str(menuitem.getSubMenu()) + '\n'
195                 #lst = str(self.getLevel(menuitem.getSubMenu(), space, lst))
196             #return lst
197         #else: return lst
198
199     #security.declareProtected(ManagePortal, 'getMenuTree')
200     #def getMenuTree(self):
201         #""" Return all submenu with it's menuitems """
202         #out = '\n'
203         #mapping = self._submenu_mapping
204         #for item in mapping.items():
205             #space = ''
206             #out += space + item[0] + '  ---  ' + str(item[1]) + '\n'
207             #if item[1] != '':
208                 #out += space + str(self.getValueByKey(item[0])) + '\n' + str(self.getLevel(self.getValueByKey(item[0]), space, lst=''))
209         #return out
210
211     security.declareProtected(ManagePortal, 'manage_addMenuItem')
212     def manage_addMenuItem(self, submenu_path, title, url=None, REQUEST=None):
213         """ Add MenuItem via ZMI """
214         self.validateTitle(title)
215         if submenu_path in self._submenu_mapping.keys():
216             self._submenu_mapping[submenu_path].append(MenuItem(title, url))
217         else:
218             self.getMenuItemByPath(submenu_path).addItem(MenuItem(title, url))
219
220         if REQUEST:
221             REQUEST['RESPONSE'].redirect( '%s/manage_editMenuItems'
222                                           '?submenu_path=%s&manage_tabs_message=MenuItem+\'%s\'+added.'
223                                         % (self.absolute_url(), submenu_path, title))
224
225     security.declareProtected(ManagePortal, 'manage_removeMenuItem')
226     def manage_removeMenuItem(self, submenu_path, REQUEST=None):
227         """ Remove MenuItem via ZMI """
228         path = submenu_path.strip().split('/')
229         if len(path)==2:
230             self._submenu_mapping[path[0]].pop(int(path[1]))
231         elif len(path)>2:
232             self.getMenuItemByPath('/'.join(path[:-1])).deleteItem(int(path[-1]))
233
234         if REQUEST:
235             REQUEST['RESPONSE'].redirect( '%s/manage_editMenuItems'
236                                           '?submenu_path=%s&manage_tabs_message=MenuItem+removed.'
237                                         % (self.absolute_url(), '/'.join(path[:-1])))
238
239     security.declareProtected(ManagePortal, 'manage_saveMenuItems')
240     def manage_saveMenuItems(self, submenu_path, REQUEST=None):
241         """  Save MenuItems for given subMenu via ZMI. """
242         records = REQUEST.get('menuitems')
243         if submenu_path in self._submenu_mapping.keys():
244             submenu = self._submenu_mapping[submenu_path]
245         else:
246             submenu = self.getSubMenuByPath(submenu_path)
247         if records and len(records) == len(submenu):
248              for i in range(len(submenu)):
249                  if records[i].get('title'): submenu[i].setTitle(records[i].get('title'))
250                  submenu[i].setUrl(records[i].get('url'))
251
252         if REQUEST:
253             REQUEST['RESPONSE'].redirect('%s/manage_editMenuItems'
254                                          '?&submenu_path=%s&manage_tabs_message=MenuItems+updated.'
255                                         % (self.absolute_url(), submenu_path))
256
257     security.declareProtected(ManagePortal, 'manage_moveMenuItemDown')
258     def manage_moveMenuItemDown(self, submenu_path, REQUEST=None):
259         """ Move the MenuItem down via ZMI """
260         path = submenu_path.strip().split('/')
261         if len(path)==2:
262             self._submenu_mapping[path[0]] = PersistentList(self.moveItem(path[1], int(path[1])+1, self._submenu_mapping[path[0]]))
263         elif len(path)>2:
264             menuitem = self.getMenuItemByPath('/'.join(path[:-1]))
265             menuitem.setMenuItems(list(self.moveItem(path[-1], int(path[-1])+1, menuitem.listMenuItems())))
266
267         if REQUEST:
268             REQUEST['RESPONSE'].redirect('%s/manage_editMenuItems'
269                                          '?&submenu_path=%s&manage_tabs_message=MenuItem+moved+up.'
270                                         % (self.absolute_url(), '/'.join(path[:-1])))
271
272     security.declareProtected(ManagePortal, 'manage_moveMenuItemUp')
273     def manage_moveMenuItemUp(self, submenu_path, REQUEST=None):
274         """ Move the MenuItem up via ZMI """
275         path = submenu_path.strip().split('/')
276         if len(path)==2:
277             self._submenu_mapping[path[0]] = PersistentList(self.moveItem(path[1], int(path[1])-1, self._submenu_mapping[path[0]]))
278         elif len(path)>2:
279             menuitem = self.getMenuItemByPath('/'.join(path[:-1]))
280             menuitem.setMenuItems(list(self.moveItem(path[-1], int(path[-1])-1, menuitem.listMenuItems())))
281
282         if REQUEST:
283             REQUEST['RESPONSE'].redirect('%s/manage_editMenuItems'
284                                          '?&submenu_path=%s&manage_tabs_message=MenuItem+moved+up.'
285                                         % (self.absolute_url(), '/'.join(path[:-1])))
286
287     security.declareProtected(ManagePortal, 'moveItem')
288     def moveItem(self, index, position, menuitems):
289         """ Move an item to the given position."""
290         if index == position:
291             return
292         elif position < 0:
293             position = 0
294         menuitems = list(menuitems)
295         menuitem = menuitems.pop(int(index))
296         menuitems.insert(int(position), menuitem)
297         return menuitems
298
299     security.declareProtected(ManagePortal, 'manage_reorderItems')
300     def manage_reorderItems(self, idxs, submenu_path):
301         """ Reorder menu items of the same submenu in given order """
302         path = submenu_path.strip().split('/')
303         submenu = self.reorderItems(idxs, self.getSubMenuByPath(submenu_path))
304         if len(path) == 1:
305             self._submenu_mapping[path[0]] = PersistentList(submenu)
306         elif len(path) > 1:
307             menuitem = self.getMenuItemByPath(submenu_path)
308             menuitem.setMenuItems(submenu)
309
310     security.declareProtected(ManagePortal, 'reorderItems')
311     def reorderItems(self, idxs, submenu):
312         """ Return list in given order """
313         idxs = list(map(int,idxs))
314         #if len(idxs) != len(submenu): return False
315         return [submenu[idx] for idx in idxs]
316
317 InitializeClass(DropDownMenuTool)
Note: See TracBrowser for help on using the browser.