Annotation of kupu/plone/plonelibrarytool.py, revision 1.1
1.1 ! dwinter 1: ##############################################################################
! 2: #
! 3: # Copyright (c) 2003-2005 Kupu Contributors. All rights reserved.
! 4: #
! 5: # This software is distributed under the terms of the Kupu
! 6: # License. See LICENSE.txt for license text. For a list of Kupu
! 7: # Contributors see CREDITS.txt.
! 8: #
! 9: ##############################################################################
! 10: """Plone Kupu library tool
! 11:
! 12: This module contains the Plone specific version of the Kupu library
! 13: tool.
! 14:
! 15: $Id: plonelibrarytool.py 15693 2005-08-05 14:14:33Z duncan $
! 16: """
! 17: import os
! 18: from ZODB.PersistentList import PersistentList
! 19: from ZODB.PersistentMapping import PersistentMapping
! 20: from AccessControl import ClassSecurityInfo
! 21: from OFS.SimpleItem import SimpleItem
! 22: import Globals
! 23: from Globals import InitializeClass
! 24:
! 25: from Products.PageTemplates.PageTemplateFile import PageTemplateFile
! 26: from Products.CMFCore.utils import UniqueObject, getToolByName
! 27:
! 28: from Products.kupu.plone.librarytool import KupuLibraryTool
! 29: from Products.kupu.plone import permissions, scanner
! 30: from Products.kupu import kupu_globals
! 31: from Products.kupu.config import TOOLNAME, TOOLTITLE
! 32:
! 33: _default_libraries = (
! 34: dict(id="root",
! 35: title="string:Home",
! 36: uri="string:${portal_url}",
! 37: src="string:${portal_url}/kupucollection.xml",
! 38: icon="string:${portal_url}/misc_/CMFPlone/plone_icon"),
! 39: dict(id="current",
! 40: title="string:Current folder",
! 41: uri="string:${folder_url}",
! 42: src="string:${folder_url}/kupucollection.xml",
! 43: icon="string:${portal_url}/folder_icon.gif"),
! 44: dict(id="myitems",
! 45: title="string:My recent items",
! 46: uri="string:${portal_url}/kupumyitems.xml",
! 47: src="string:${portal_url}/kupumyitems.xml",
! 48: icon="string:${portal_url}/kupuimages/kupusearch_icon.gif"),
! 49: dict(id="recentitems",
! 50: title="string:Recent items",
! 51: uri="string:${portal_url}/kupurecentitems.xml",
! 52: src="string:${portal_url}/kupurecentitems.xml",
! 53: icon="string:${portal_url}/kupuimages/kupusearch_icon.gif")
! 54: )
! 55:
! 56: _default_resource_types = {
! 57: 'collection': ('Plone Site', 'Folder', 'Large Plone Folder'),
! 58: 'mediaobject': ('Image',),
! 59: 'linkable': ('Document', 'Image', 'File', 'News Item', 'Event')
! 60: }
! 61:
! 62: # Tidy up html by exlcluding lots of things.
! 63: _excluded_html = [
! 64: (('center', 'span', 'tt', 'big', 'small', 'u', 's', 'strike', 'basefont', 'font'), ()),
! 65: ((), ('dir','lang','valign','halign','border','frame','rules','cellspacing','cellpadding','bgcolor')),
! 66: (('table','th','td'),('width','height')),
! 67: ]
! 68:
! 69: # Default should list all styles used by Kupu
! 70: _style_whitelist = ['text-align', 'list-style-type', 'float']
! 71:
! 72: _default_paragraph_styles = (
! 73: "Heading|h2|Heading",
! 74: "Subheading|h3|Subheading",
! 75: "Formatted|pre",
! 76: )
! 77:
! 78: class PloneKupuLibraryTool(UniqueObject, SimpleItem, KupuLibraryTool):
! 79: """Plone specific version of the kupu library tool"""
! 80:
! 81: id = TOOLNAME
! 82: meta_type = "Kupu Library Tool"
! 83: title = TOOLTITLE
! 84: security = ClassSecurityInfo()
! 85:
! 86: # protect methods provided by super class KupuLibraryTool
! 87: security.declareProtected(permissions.QueryLibraries, "getLibraries",
! 88: "getPortalTypesForResourceType")
! 89: security.declareProtected(permissions.ManageLibraries, "addLibrary",
! 90: "deleteLibraries", "updateLibraries",
! 91: "moveUp", "moveDown")
! 92: security.declareProtected(permissions.ManageLibraries, "addResourceType",
! 93: "updateResourceTypes", "deleteResourceTypes")
! 94:
! 95: def __init__(self):
! 96: self._libraries = PersistentList()
! 97: self._res_types = PersistentMapping()
! 98: self.linkbyuid = True
! 99:
! 100: def manage_afterAdd(self, item, container):
! 101: # We load default values here, so __init__ can still be used
! 102: # in unit tests. Plus, it only makes sense to load these if
! 103: # we're being added to a Plone site anyway
! 104: for lib in _default_libraries:
! 105: self.addLibrary(**lib)
! 106: self._res_types.update(_default_resource_types)
! 107:
! 108: security.declareProtected('View', "getLinkbyuid")
! 109: def getLinkbyuid(self):
! 110: """Returns 'is linking by UID enabled'?"""
! 111: try:
! 112: return self.linkbyuid
! 113: except AttributeError:
! 114: return 1
! 115:
! 116: security.declareProtected('View', "getTableClassnames")
! 117: def getTableClassnames(self):
! 118: """Return a list of classnames supported in tables"""
! 119: try:
! 120: return self.table_classnames
! 121: except AttributeError:
! 122: return ('plain', 'listing', 'vertical listing', 'listing nosort')
! 123:
! 124: security.declareProtected('View', "getParagraphStyles")
! 125: def getParagraphStyles(self):
! 126: """Return a list of classnames supported in tables"""
! 127: try:
! 128: return self.paragraph_styles
! 129: except AttributeError:
! 130: return _default_paragraph_styles
! 131:
! 132: security.declareProtected('View', "getHtmlExclusions")
! 133: def getHtmlExclusions(self):
! 134: try:
! 135: return self.html_exclusions
! 136: except AttributeError:
! 137: self.html_exclusions = _excluded_html
! 138: return self.html_exclusions
! 139:
! 140: security.declareProtected('View', "getStyleWhitelist")
! 141: def getStyleWhitelist(self):
! 142: try:
! 143: return self.style_whitelist
! 144: except AttributeError:
! 145: self.style_whitelist = _style_whitelist
! 146: return self.style_whitelist
! 147:
! 148: security.declareProtected('View', "getClassBlacklist")
! 149: def getClassBlacklist(self):
! 150: return getattr(self, 'class_blacklist', [])
! 151:
! 152: security.declareProtected('View', "getClassBlacklist")
! 153: def installBeforeUnload(self):
! 154: return getattr(self, 'install_beforeunload', True)
! 155:
! 156: security.declareProtected('View', 'isKupuEnabled')
! 157: def isKupuEnabled(self, useragent='', allowAnonymous=False, REQUEST=None):
! 158: def numerics(s):
! 159: '''Convert a string into a tuple of all digit sequences
! 160: '''
! 161: seq = ['']
! 162: for c in s:
! 163: if c.isdigit():
! 164: seq[-1] = seq[-1] + c
! 165: elif seq[-1]:
! 166: seq.append('')
! 167: return tuple([ int(val) for val in seq if val])
! 168:
! 169: # First check whether the user actually wants kupu
! 170: pm = getToolByName(self, 'portal_membership')
! 171: if pm.isAnonymousUser() and not allowAnonymous:
! 172: return False
! 173:
! 174: user = pm.getAuthenticatedMember()
! 175: if user.getProperty('wysiwyg_editor').lower() != 'kupu':
! 176: return False
! 177:
! 178: # Then check whether their browser supports it.
! 179: if not useragent:
! 180: useragent = REQUEST['HTTP_USER_AGENT']
! 181:
! 182: if 'Opera' in useragent or 'BEOS' in useragent:
! 183: return False
! 184:
! 185: if not useragent.startswith('Mozilla/'):
! 186: return False
! 187:
! 188: try:
! 189: mozillaver = numerics(useragent[len('Mozilla/'):].split(' ')[0])
! 190: if mozillaver > (5,0):
! 191: return True
! 192: elif mozillaver == (5,0):
! 193: rv = useragent.find(' rv:')
! 194: if rv >= 0:
! 195: verno = numerics(useragent[rv+4:].split(')')[0])
! 196: return verno >= (1,3,1)
! 197:
! 198: MSIE = useragent.find('MSIE')
! 199: if MSIE >= 0:
! 200: verno = numerics(useragent[MSIE+4:].split(';')[0])
! 201: return verno >= (5,5)
! 202:
! 203: except:
! 204: # In case some weird browser makes the test code blow up.
! 205: pass
! 206: return False
! 207:
! 208: # ZMI views
! 209: manage_options = (SimpleItem.manage_options[1:] + (
! 210: dict(label='Config', action='kupu_config'),
! 211: dict(label='Libraries', action='zmi_libraries'),
! 212: dict(label='Resource types', action='zmi_resource_types'),
! 213: dict(label='Documentation', action='zmi_docs'),
! 214: dict(label='Status', action='sanity_check'),
! 215: ))
! 216:
! 217:
! 218: security.declarePublic('scanIds')
! 219: def scanIds(self):
! 220: """Finds the relevant source files and the doller/Id/dollar strings they contain"""
! 221: return scanner.scanIds()
! 222:
! 223: security.declarePublic('scanKWS')
! 224: def scanKWS(self):
! 225: """Check that kupu_wysiwyg_support is up to date"""
! 226: return scanner.scanKWS()
! 227:
! 228: security.declarePublic('docs')
! 229: def docs(self):
! 230: """Returns Kupu docs formatted as HTML"""
! 231: docpath = os.path.join(Globals.package_home(kupu_globals), 'doc')
! 232: f = open(os.path.join(docpath, 'PLONE2.txt'), 'r')
! 233: _docs = f.read()
! 234: return _docs
! 235:
! 236: security.declareProtected(permissions.ManageLibraries, "zmi_docs")
! 237: zmi_docs = PageTemplateFile("zmi_docs.pt", globals())
! 238: zmi_docs.title = 'kupu configuration documentation'
! 239:
! 240: security.declareProtected(permissions.ManageLibraries, "sanity_check")
! 241: sanity_check = PageTemplateFile("sanity_check.pt", globals())
! 242: sanity_check.title = 'kupu status'
! 243:
! 244: security.declareProtected(permissions.ManageLibraries, "kupu_config")
! 245: kupu_config = PageTemplateFile("kupu_config.pt", globals())
! 246: kupu_config.title = 'kupu configuration'
! 247:
! 248: security.declareProtected(permissions.ManageLibraries, "zmi_libraries")
! 249: zmi_libraries = PageTemplateFile("libraries.pt", globals())
! 250: zmi_libraries.title = 'kupu configuration'
! 251:
! 252: security.declareProtected(permissions.ManageLibraries, "zmi_resource_types")
! 253: zmi_resource_types = PageTemplateFile("resource_types.pt", globals())
! 254: zmi_resource_types.title = 'kupu configuration'
! 255:
! 256: security.declareProtected(permissions.ManageLibraries,
! 257: "zmi_get_libraries")
! 258: def zmi_get_libraries(self):
! 259: """Return the libraries sequence for the ZMI view"""
! 260: #return ()
! 261: def text(value):
! 262: return getattr(value, 'text', value)
! 263: return [dict([(key, text(value)) for key, value in lib.items()])
! 264: for lib in self._libraries]
! 265:
! 266: security.declareProtected(permissions.ManageLibraries,
! 267: "zmi_add_library")
! 268: def zmi_add_library(self, id, title, uri, src, icon, REQUEST):
! 269: """Add a library through the ZMI"""
! 270: self.addLibrary(id, title, uri, src, icon)
! 271: REQUEST.RESPONSE.redirect(self.absolute_url() + '/zmi_libraries')
! 272:
! 273: security.declareProtected(permissions.ManageLibraries,
! 274: "zmi_update_libraries")
! 275: def zmi_update_libraries(self, libraries, REQUEST):
! 276: """Update libraries through the ZMI"""
! 277: self.updateLibraries(libraries)
! 278: REQUEST.RESPONSE.redirect(self.absolute_url() + '/zmi_libraries')
! 279:
! 280: security.declareProtected(permissions.ManageLibraries,
! 281: "zmi_delete_libraries")
! 282: def zmi_delete_libraries(self, indices, REQUEST):
! 283: """Delete libraries through the ZMI"""
! 284: self.deleteLibraries(indices)
! 285: REQUEST.RESPONSE.redirect(self.absolute_url() + '/zmi_libraries')
! 286:
! 287: security.declareProtected(permissions.ManageLibraries,
! 288: "zmi_move_up")
! 289: def zmi_move_up(self, indices, REQUEST):
! 290: """Move libraries up through the ZMI"""
! 291: self.moveUp(indices)
! 292: REQUEST.RESPONSE.redirect(self.absolute_url() + '/zmi_libraries')
! 293:
! 294: security.declareProtected(permissions.ManageLibraries,
! 295: "zmi_move_down")
! 296: def zmi_move_down(self, indices, REQUEST):
! 297: """Move libraries down through the ZMI"""
! 298: self.moveDown(indices)
! 299: REQUEST.RESPONSE.redirect(self.absolute_url() + '/zmi_libraries')
! 300:
! 301: security.declarePublic("zmi_get_default_library")
! 302: def zmi_get_default_library(self):
! 303: """Return the default selected library for the ZMI view"""
! 304: return getattr(self, '_default_library', '')
! 305:
! 306: security.declareProtected(permissions.ManageLibraries,
! 307: "zmi_set_default_library")
! 308: def zmi_set_default_library(self, defid=''):
! 309: """Return the libraries sequence for the ZMI view"""
! 310: self._default_library = defid
! 311:
! 312: security.declareProtected(permissions.ManageLibraries,
! 313: "zmi_get_type_mapping")
! 314: def zmi_get_type_mapping(self):
! 315: """Return the type mapping for the ZMI view"""
! 316: return [(res_type, tuple(portal_type)) for res_type, portal_type
! 317: in self._res_types.items()]
! 318:
! 319: security.declareProtected(permissions.ManageLibraries,
! 320: "zmi_add_resource_type")
! 321: def zmi_add_resource_type(self, resource_type, portal_types, REQUEST):
! 322: """Add resource type through the ZMI"""
! 323: self.addResourceType(resource_type, portal_types)
! 324: REQUEST.RESPONSE.redirect(self.absolute_url() + '/zmi_resource_types')
! 325:
! 326: security.declareProtected(permissions.ManageLibraries,
! 327: "zmi_update_resource_types")
! 328: def zmi_update_resource_types(self, type_info, REQUEST):
! 329: """Update resource types through the ZMI"""
! 330: self.updateResourceTypes(type_info)
! 331: REQUEST.RESPONSE.redirect(self.absolute_url() + '/zmi_resource_types')
! 332:
! 333: security.declareProtected(permissions.ManageLibraries,
! 334: "zmi_delete_resource_types")
! 335: def zmi_delete_resource_types(self, resource_types, REQUEST):
! 336: """Delete resource types through the ZMI"""
! 337: self.deleteResourceTypes(resource_types)
! 338: REQUEST.RESPONSE.redirect(self.absolute_url() + '/zmi_resource_types')
! 339:
! 340: security.declareProtected(permissions.ManageLibraries,
! 341: "configure_kupu")
! 342: def configure_kupu(self,
! 343: linkbyuid, table_classnames, html_exclusions, style_whitelist, class_blacklist,
! 344: installBeforeUnload=None, parastyles=None,
! 345: REQUEST=None):
! 346: """Delete resource types through the ZMI"""
! 347: self.linkbyuid = int(linkbyuid)
! 348: self.table_classnames = table_classnames
! 349: if installBeforeUnload is not None:
! 350: self.install_beforeunload = bool(installBeforeUnload)
! 351: if parastyles:
! 352: self.paragraph_styles = [ line.strip() for line in parastyles if line.strip() ]
! 353:
! 354: newex = html_exclusions[-1]
! 355:
! 356: html_exclusions = [ (tuple(h.get('tags', ())), tuple(h.get('attributes', ())))
! 357: for h in html_exclusions[:-1] if h.get('keep')]
! 358:
! 359: tags, attr = newex.get('tags', ()), newex.get('attributes', ())
! 360: if tags or attr:
! 361: tags = tuple(tags.replace(',',' ').split())
! 362: attr = tuple(attr.replace(',',' ').split())
! 363: html_exclusions.append((tags, attr))
! 364:
! 365: self.html_exclusions = html_exclusions
! 366:
! 367: self.style_whitelist = list(style_whitelist)
! 368: self.class_blacklist = list(class_blacklist)
! 369:
! 370: if REQUEST:
! 371: REQUEST.RESPONSE.redirect(self.absolute_url() + '/kupu_config')
! 372:
! 373: InitializeClass(PloneKupuLibraryTool)
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>