[1] | 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) |
---|