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) |
---|