Commit 3a5d229b authored by 's avatar

Split out property management.

parent cec4f361
......@@ -87,13 +87,14 @@
Folders are the basic container objects and are analogous to directories.
$Id: Folder.py,v 1.55 1998/12/04 20:15:29 jim Exp $"""
$Id: Folder.py,v 1.56 1999/01/06 23:20:06 brian Exp $"""
__version__='$Revision: 1.55 $'[11:-2]
__version__='$Revision: 1.56 $'[11:-2]
from Globals import HTMLFile
from ObjectManager import ObjectManager
from PropertyManager import PropertyManager
from CopySupport import CopyContainer
from FindSupport import FindSupport
from Image import Image, File
......@@ -122,8 +123,13 @@ def manage_addFolder(self,id,title='',createPublic=0,createUserF=0,
if createPublic: i.manage_addDocument(id='index_html',title='')
if REQUEST is not None: return self.manage_main(self,REQUEST,update_menu=1)
class Folder(ObjectManager,RoleManager,DocumentHandler,
SimpleItem.Item,CopyContainer,FindSupport):
class Folder(ObjectManager,
PropertyManager,
RoleManager,
DocumentHandler,
SimpleItem.Item,
CopyContainer,
FindSupport):
"""
The basic container object in Principia. Folders can hold almost all
other Principia objects.
......
......@@ -84,10 +84,11 @@
##############################################################################
"""Image object"""
__version__='$Revision: 1.47 $'[11:-2]
__version__='$Revision: 1.48 $'[11:-2]
import Globals
from Globals import HTMLFile, MessageDialog
from PropertyManager import PropertyManager
from AccessControl.Role import RoleManager
from SimpleItem import Item_w__name__
from Globals import Persistent
......@@ -99,18 +100,15 @@ manage_addFileForm=HTMLFile('imageAdd', globals(),Kind='File',kind='file')
def manage_addFile(self,id,file,title='',precondition='',REQUEST=None):
"""Add a new File object.
Creates a new file object 'id' with the contents of 'file'"""
Creates a new File object 'id' with the contents of 'file'"""
id, title = cookId(id, title, file)
self._setObject(id, File(id,title,file,precondition))
if REQUEST is not None: return self.manage_main(self,REQUEST)
class File(Persistent,Implicit,RoleManager,Item_w__name__):
"""
Principia object for arbitrary files. A Files string representation is
its contents.
"""
class File(Persistent,Implicit,PropertyManager,RoleManager,Item_w__name__):
"""A File object is a content object for arbitrary files."""
meta_type='File'
icon='p_/file'
......@@ -122,6 +120,7 @@ class File(Persistent,Implicit,RoleManager,Item_w__name__):
manage_options=({'label':'Edit', 'action':'manage_main'},
{'label':'Upload', 'action':'manage_uploadForm'},
{'label':'Properties', 'action':'manage_propertiesForm'},
{'label':'View', 'action':''},
{'label':'Security', 'action':'manage_access'},
)
......@@ -132,9 +131,18 @@ class File(Persistent,Implicit,RoleManager,Item_w__name__):
('Change Images and Files', ['manage_edit','manage_upload','PUT']),
('View',
['index_html','view_image_or_file','getSize','getContentType', '']),
('Manage properties', ('manage_addProperty',
'manage_editProperties',
'manage_delProperties',
'manage_changeProperties',)),
)
_properties=({'id':'title', 'type': 'string'},
{'id':'content_type', 'type':'string'},
)
def __init__(self,id,title,file,content_type='application/octet-stream',
precondition=''):
......@@ -272,6 +280,7 @@ class Image(File):
manage_options=({'label':'Edit', 'action':'manage_main'},
{'label':'Upload', 'action':'manage_uploadForm'},
{'label':'Properties', 'action':'manage_propertiesForm'},
{'label':'View', 'action':'view_image_or_file'},
{'label':'Security', 'action':'manage_access'},
)
......
......@@ -84,19 +84,16 @@
##############################################################################
__doc__="""Object Manager
$Id: ObjectManager.py,v 1.48 1998/12/04 20:15:30 jim Exp $"""
$Id: ObjectManager.py,v 1.49 1999/01/06 23:20:06 brian Exp $"""
__version__='$Revision: 1.48 $'[11:-2]
__version__='$Revision: 1.49 $'[11:-2]
import App.Management, Acquisition, App.Undo, Globals
import App.FactoryDispatcher
from Globals import HTMLFile, HTMLFile, Persistent
from Globals import MessageDialog, default__class_init__
from string import find,join,lower,split
from urllib import quote
from DocumentTemplate import html_quote
from ZPublisher.Converters import type_converters
from DateTime import DateTime
class ObjectManager(
App.Management.Navigation,
......@@ -119,7 +116,7 @@ class ObjectManager(
_properties =({'id':'title', 'type': 'string'},)
manage_main =HTMLFile('main', globals())
manage_propertiesForm=HTMLFile('properties', globals())
manage_options=(
{'icon':icon, 'label':'Objects',
......@@ -409,176 +406,3 @@ class ObjectManager(
return self.manage_main(self, REQUEST, update_menu=1)
def _setProperty(self,id,value,type='string'):
self._checkId(id)
self._properties=self._properties+({'id':id,'type':type},)
setattr(self,id,value)
def _delProperty(self,id):
delattr(self,id)
self._properties=tuple(filter(lambda i, n=id: i['id'] != n,
self._properties))
def propertyIds(self):
""" Return a list of property ids """
return map(lambda i: i['id'], self._properties)
def propertyValues(self):
""" Return a list of actual property objects """
return map(lambda i,s=self: getattr(s,i['id']), self._properties)
def propertyItems(self):
""" Return a list of (id,property) tuples """
return map(lambda i,s=self: (i['id'],getattr(s,i['id'])),
self._properties)
def propertyMap(self):
""" Return a tuple of mappings, giving meta-data for properties """
return self._properties
def propertyMap_d(self):
v=self._properties
try: n=self._reserved_names
except: return v
return filter(lambda x,r=n: x['id'] not in r, v)
def manage_addProperty(self,id,value,type,REQUEST=None):
"""Add a new property (www)
Sets a new property with id, type, and value.
"""
try: value=type_converters[type](value)
except: pass
self._setProperty(id,value,type)
if REQUEST is not None:
return self.manage_propertiesForm(self, REQUEST)
def manage_editProperties(self,REQUEST):
"""Edit object properties"""
for p in self._properties:
n=p['id']
try: setattr(self,n,REQUEST[n])
except: setattr(self,n,'')
return MessageDialog(
title ='Success!',
message='Your changes have been saved',
action ='manage_propertiesForm')
def manage_changeProperties(self, REQUEST=None, **kw):
"""Change existing object properties.
Change object properties by passing either a mapping object
of name:value pairs {'foo':6} or passing name=value parameters
"""
if REQUEST is None:
props={}
else:
props=REQUEST
if kw:
for name, value in kw.items():
props[name]=value
for name, value in props.items():
if self.hasProperty(name):
setattr(self, name, value)
if REQUEST is not None:
return MessageDialog(
title ='Success!',
message='Your changes have been saved',
action ='manage_propertiesForm')
def hasProperty(self, id):
"""returns 1 if object has a settable property 'id'"""
for p in self._properties:
if id == p['id']: return 1
return 0
def manage_delProperties(self,ids,REQUEST=None):
"""Delete one or more properties
Deletes properties specified by 'ids'
"""
try: p=self._reserved_names
except: p=()
if ids is None:
return MessageDialog(title='No property specified',
message='No properties were specified!',
action ='./manage_propertiesForm',)
for n in ids:
if n in p:
return MessageDialog(
title ='Cannot delete %s' % n,
message='The property <I>%s</I> cannot be deleted.' % n,
action ='manage_propertiesForm')
try: self._delProperty(n)
except: raise 'BadRequest', (
'The property <I>%s</I> does not exist' % n)
if REQUEST is not None:
return self.manage_propertiesForm(self, REQUEST)
def _defaultInput(self,n,t,v):
return '<INPUT NAME="%s:%s" SIZE="40" VALUE="%s"></TD>' % (n,t,v)
def _stringInput(self,n,t,v):
return ('<INPUT NAME="%s:%s" SIZE="40" VALUE="%s"></TD>'
% (n,t,html_quote(v)))
def _booleanInput(self,n,t,v):
if v: v="CHECKED"
else: v=''
return ('<INPUT TYPE="CHECKBOX" NAME="%s:%s" SIZE="50" %s></TD>'
% (n,t,v))
def _selectInput(self,n,t,v):
s=['<SELECT NAME="%s:%s">' % (n,t)]
map(lambda i: s.append('<OPTION>%s' % i), v)
s.append('</SELECT>')
return join(s,'\n')
def _linesInput(self,n,t,v):
try: v=html_quote(join(v,'\n'))
except: v=''
return (
'<TEXTAREA NAME="%s:lines" ROWS="10" COLS="40">%s</TEXTAREA>'
% (n,v))
def _tokensInput(self,n,t,v):
try: v=html_quote(join(v,' '))
except: v=''
return ('<INPUT NAME="%s:%s" SIZE="40" VALUE="%s"></TD>'
% (n,t,html_quote(v)))
def _textInput(self,n,t,v):
return ('<TEXTAREA NAME="%s:text" ROWS="10" COLS="40">%s</TEXTAREA>'
% (n,html_quote(v)))
_inputMap={
'float': _defaultInput,
'int': _defaultInput,
'long': _defaultInput,
'string': _stringInput,
'lines': _linesInput,
'text': _textInput,
'date': _defaultInput,
'tokens': _tokensInput,
# 'boolean': _booleanInput,
}
propertyTypes=map(lambda key: (lower(key), key), _inputMap.keys())
propertyTypes.sort()
propertyTypes=map(lambda key:
{'id': key[1],
'selected': key[1]=='string' and 'SELECTED' or ''},
propertyTypes)
def propertyInputs(self):
imap=self._inputMap
r=[]
for p in self._properties:
n=p['id']
t=p['type']
v=getattr(self,n)
r.append({'id': n, 'input': imap[t](None,n,t,v)})
return r
##############################################################################
#
# Zope Public License (ZPL) Version 0.9.4
# ---------------------------------------
#
# Copyright (c) Digital Creations. All rights reserved.
#
# Redistribution and use in source and binary forms, with or
# without modification, are permitted provided that the following
# conditions are met:
#
# 1. Redistributions in source code must retain the above
# copyright notice, this list of conditions, and the following
# disclaimer.
#
# 2. Redistributions in binary form must reproduce the above
# copyright notice, this list of conditions, and the following
# disclaimer in the documentation and/or other materials
# provided with the distribution.
#
# 3. Any use, including use of the Zope software to operate a
# website, must either comply with the terms described below
# under "Attribution" or alternatively secure a separate
# license from Digital Creations.
#
# 4. All advertising materials, documentation, or technical papers
# mentioning features derived from or use of this software must
# display the following acknowledgement:
#
# "This product includes software developed by Digital
# Creations for use in the Z Object Publishing Environment
# (http://www.zope.org/)."
#
# 5. Names associated with Zope or Digital Creations must not be
# used to endorse or promote products derived from this
# software without prior written permission from Digital
# Creations.
#
# 6. Redistributions of any form whatsoever must retain the
# following acknowledgment:
#
# "This product includes software developed by Digital
# Creations for use in the Z Object Publishing Environment
# (http://www.zope.org/)."
#
# 7. Modifications are encouraged but must be packaged separately
# as patches to official Zope releases. Distributions that do
# not clearly separate the patches from the original work must
# be clearly labeled as unofficial distributions.
#
# Disclaimer
#
# THIS SOFTWARE IS PROVIDED BY DIGITAL CREATIONS ``AS IS'' AND
# ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
# FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
# SHALL DIGITAL CREATIONS OR ITS CONTRIBUTORS BE LIABLE FOR ANY
# DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
# IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
# THE POSSIBILITY OF SUCH DAMAGE.
#
# Attribution
#
# Individuals or organizations using this software as a web site
# must provide attribution by placing the accompanying "button"
# and a link to the accompanying "credits page" on the website's
# main entry point. In cases where this placement of
# attribution is not feasible, a separate arrangment must be
# concluded with Digital Creations. Those using the software
# for purposes other than web sites must provide a corresponding
# attribution in locations that include a copyright using a
# manner best suited to the application environment.
#
# This software consists of contributions made by Digital
# Creations and many individuals on behalf of Digital Creations.
# Specific attributions are listed in the accompanying credits
# file.
#
##############################################################################
"""Property management"""
__version__='$Revision: 1.1 $'[11:-2]
## from ObjectManager import ObjectManager
## from CopySupport import CopyContainer
## from FindSupport import FindSupport
## from Image import Image, File
## from Document import DocumentHandler
## from AccessControl.Role import RoleManager
## import SimpleItem
## from string import rfind, lower
## from content_types import content_type, find_binary, text_type
## import Globals
from ZPublisher.Converters import type_converters
from string import find,join,lower,split
from DocumentTemplate import html_quote
from DateTime import DateTime
from Globals import HTMLFile
def aq_base(ob):
if hasattr(ob, 'aq_base'):
return ob.aq_base
return ob
class PropertyManager:
"""
The PropertyManager mixin class provides an object with
transparent property management. An object which wants to
have properties should inherit from PropertyManager.
An object which inherits from PropertyManager should include
the following entry in its manage_options structure:
{'label':'Properties', 'action':'manage_propertiesForm',}
An object which inherits from PropertyManager should also
include the following entry in its __ac_permissions__
structure:
('Manage properties', ('manage_addProperty',
'manage_editProperties',
'manage_delProperties',
'manage_changeProperties',)),
"""
manage_propertiesForm=HTMLFile('properties', globals())
_properties=({'id':'title', 'type': 'string'},)
_reserved_names=()
def valid_property_id(self, id):
if not id or id[:1]=='_' or hasattr(aq_base(self), id):
return 0
return 1
def getProperty(self, id, d=None):
"""Get the property 'id', returning the optional second
argument or None if no such property is found."""
if self.hasProperty(id):
return getattr(self, id)
return d
def _setProperty(self, id, value, type='string'):
if not self.valid_property_id(id):
raise 'Bad Request', 'Invalid property id'
self._properties=self._properties+({'id':id,'type':type},)
setattr(self,id,value)
def hasProperty(self, id):
"""Return true if object has a property 'id'"""
for p in self._properties:
if id==p['id']:
return 1
return 0
def _delProperty(self, id):
if not self.hasProperty(id):
raise ValueError, 'The property %s does not exist' % id
delattr(self,id)
self._properties=tuple(filter(lambda i, n=id: i['id'] != n,
self._properties))
def propertyIds(self):
"""Return a list of property ids """
return map(lambda i: i['id'], self._properties)
def propertyValues(self):
"""Return a list of actual property objects """
return map(lambda i,s=self: getattr(s,i['id']), self._properties)
def propertyItems(self):
"""Return a list of (id,property) tuples """
return map(lambda i,s=self: (i['id'],getattr(s,i['id'])),
self._properties)
def propertyMap(self):
"""Return a tuple of mappings, giving meta-data for properties """
return self._properties
def propertyMap_d(self):
v=self._properties
try: n=self._reserved_names
except: return v
return filter(lambda x,r=n: x['id'] not in r, v)
# Web interface
def manage_addProperty(self, id, value, type, REQUEST=None):
"""Add a new property via the web. Sets a new property with
the given id, type, and value."""
if type_converters.has_key(type):
value=type_converters[type](value)
self._setProperty(id, value, type)
if REQUEST is not None:
return self.manage_propertiesForm(self, REQUEST)
def manage_editProperties(self, REQUEST):
"""Edit object properties via the web."""
for p in self._properties:
n=p['id']
setattr(self, n, REQUEST.get(n, ''))
return MessageDialog(
title ='Success!',
message='Your changes have been saved',
action ='manage_propertiesForm')
def manage_changeProperties(self, REQUEST=None, **kw):
"""Change existing object properties.
Change object properties by passing either a mapping object
of name:value pairs {'foo':6} or passing name=value parameters
"""
if REQUEST is None:
props={}
else:
props=REQUEST
if kw:
for name, value in kw.items():
props[name]=value
for name, value in props.items():
if self.hasProperty(name):
setattr(self, name, value)
if REQUEST is not None:
return MessageDialog(
title ='Success!',
message='Your changes have been saved',
action ='manage_propertiesForm')
def manage_delProperties(self, ids=None, REQUEST=None):
"""Delete one or more properties
Deletes properties specified by 'ids'
"""
if ids is None:
return MessageDialog(
title='No property specified',
message='No properties were specified!',
action ='./manage_propertiesForm',)
rnames=self._reserved_names
for n in ids:
if n in rnames:
return MessageDialog(
title ='Cannot delete %s' % n,
message='The property <I>%s</I> cannot be deleted.' % n,
action ='manage_propertiesForm')
try: self._delProperty(n)
except: raise 'BadRequest', (
'The property <I>%s</I> does not exist' % n)
if REQUEST is not None:
return self.manage_propertiesForm(self, REQUEST)
def _defaultInput(self,n,t,v):
return '<INPUT NAME="%s:%s" SIZE="40" VALUE="%s"></TD>' % (n,t,v)
def _stringInput(self,n,t,v):
return ('<INPUT NAME="%s:%s" SIZE="40" VALUE="%s"></TD>'
% (n,t,html_quote(v)))
def _booleanInput(self,n,t,v):
if v: v="CHECKED"
else: v=''
return ('<INPUT TYPE="CHECKBOX" NAME="%s:%s" SIZE="50" %s></TD>'
% (n,t,v))
def _selectInput(self,n,t,v):
s=['<SELECT NAME="%s:%s">' % (n,t)]
map(lambda i: s.append('<OPTION>%s' % i), v)
s.append('</SELECT>')
return join(s,'\n')
def _linesInput(self,n,t,v):
try: v=html_quote(join(v,'\n'))
except: v=''
return (
'<TEXTAREA NAME="%s:lines" ROWS="10" COLS="40">%s</TEXTAREA>'
% (n,v))
def _tokensInput(self,n,t,v):
try: v=html_quote(join(v,' '))
except: v=''
return ('<INPUT NAME="%s:%s" SIZE="40" VALUE="%s"></TD>'
% (n,t,html_quote(v)))
def _textInput(self,n,t,v):
return ('<TEXTAREA NAME="%s:text" ROWS="10" COLS="40">%s</TEXTAREA>'
% (n,html_quote(v)))
_inputMap={
'float': _defaultInput,
'int': _defaultInput,
'long': _defaultInput,
'string': _stringInput,
'lines': _linesInput,
'text': _textInput,
'date': _defaultInput,
'tokens': _tokensInput,
# 'boolean': _booleanInput,
}
propertyTypes=map(lambda key: (lower(key), key), _inputMap.keys())
propertyTypes.sort()
propertyTypes=map(lambda key:
{'id': key[1],
'selected': key[1]=='string' and 'SELECTED' or ''},
propertyTypes)
def propertyInputs(self):
imap=self._inputMap
r=[]
for p in self._properties:
n=p['id']
t=p['type']
v=getattr(self,n)
r.append({'id': n, 'input': imap[t](None,n,t,v)})
return r
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment