Commit 2b13e39f authored by iv's avatar iv

ERP5Workflow: WIP for folder comparison

parent b1d54882
"""
Object Manager
"""
from cgi import escape
from cStringIO import StringIO
from logging import getLogger
import copy
import fnmatch
import marshal
import os
import re
import sys
from types import NoneType
from AccessControl import ClassSecurityInfo
from AccessControl.class_init import InitializeClass
from AccessControl.Permission import getPermissions
from AccessControl.Permissions import view_management_screens
from AccessControl.Permissions import access_contents_information
from AccessControl.Permissions import delete_objects
from AccessControl.Permissions import ftp_access
from AccessControl.Permissions import import_export_objects
from AccessControl import getSecurityManager
from AccessControl.ZopeSecurityPolicy import getRoles
from Acquisition import aq_base
from Acquisition import Implicit
from App.Common import is_acquired
from App.config import getConfiguration
from App.Dialogs import MessageDialog
from App.FactoryDispatcher import ProductDispatcher
from App.Management import Navigation
from App.Management import Tabs
from App.special_dtml import DTMLFile
from Persistence import Persistent
from webdav.Collection import Collection
from webdav.Lockable import ResourceLockedError
from webdav.NullResource import NullResource
from zExceptions import BadRequest
from zope.interface import implements
from zope.component.interfaces import ComponentLookupError
from zope.event import notify
from zope.lifecycleevent import ObjectAddedEvent
from zope.lifecycleevent import ObjectRemovedEvent
from zope.container.contained import notifyContainerModified
from OFS.CopySupport import CopyContainer
from OFS.interfaces import IObjectManager
from OFS.Traversable import Traversable
from OFS.event import ObjectWillBeAddedEvent
from OFS.event import ObjectWillBeRemovedEvent
from OFS.subscribers import compatibilityCall
from OFS.XMLExportImport import importXML
from OFS.XMLExportImport import exportXML
from OFS.XMLExportImport import magic
from Products.ERP5Type.Utils import sortValueList
from Products.ERP5Type.Base import Base
from Folder import FolderMixIn, OFS_HANDLER
from Products.ERP5Type import Permissions
# Constants: __replaceable__ flags:
NOT_REPLACEABLE = 0
REPLACEABLE = 1
UNIQUE = 2
LOG = getLogger('ObjectManager')
# the name BadRequestException is relied upon by 3rd-party code
BadRequestException = BadRequest
customImporters={magic: importXML,}
bad_id=re.compile(r'[^a-zA-Z0-9-_~,.$\(\)# @]').search
def checkValidId(self, id, allow_dup=0):
# If allow_dup is false, an error will be raised if an object
# with the given id already exists. If allow_dup is true,
# only check that the id string contains no illegal chars;
# check_valid_id() will be called again later with allow_dup
# set to false before the object is added.
import Globals # for data
if not id or not isinstance(id, str):
if isinstance(id, unicode):
id = escape(id)
raise BadRequest, ('Empty or invalid id specified', id)
if bad_id(id) is not None:
raise BadRequest, (
'The id "%s" contains characters illegal in URLs.' % escape(id))
if id in ('.', '..'): raise BadRequest, (
'The id "%s" is invalid because it is not traversable.' % id)
if id.startswith('_'): raise BadRequest, (
'The id "%s" is invalid because it begins with an underscore.' % id)
if id.startswith('aq_'): raise BadRequest, (
'The id "%s" is invalid because it begins with "aq_".' % id)
if id.endswith('__'): raise BadRequest, (
'The id "%s" is invalid because it ends with two underscores.' % id)
if not allow_dup:
obj = getattr(self, id, None)
if obj is not None:
# An object by the given id exists either in this
# ObjectManager or in the acquisition path.
flags = getattr(obj, '__replaceable__', NOT_REPLACEABLE)
if hasattr(aq_base(self), id):
# The object is located in this ObjectManager.
if not flags & REPLACEABLE:
raise BadRequest, (
'The id "%s" is invalid - it is already in use.' % id)
# else the object is replaceable even if the UNIQUE
# flag is set.
elif flags & UNIQUE:
raise BadRequest, ('The id "%s" is reserved.' % id)
if id == 'REQUEST':
raise BadRequest, 'REQUEST is a reserved name.'
if '/' in id:
raise BadRequest, (
'The id "%s" contains characters illegal in URLs.' % id)
class BeforeDeleteException(Exception):
pass # raise to veto deletion
class BreakoutException(Exception):
pass # raised to break out of loops
_marker=[]
class ERP5OFSFolder(CopyContainer, Base, FolderMixIn):
# Declarative security
security = ClassSecurityInfo()
security.declareObjectProtected(Permissions.AccessContentsInformation)
# don't use ERP5Type.Core.Folder methods being specific to B-Tree folders
_folder_handler = OFS_HANDLER
meta_type = 'Object Manager'
meta_types=() # Sub-object types that are specific to this object
_objects = ()
security.declareProtected(view_management_screens, 'manage_main')
manage_main=DTMLFile('dtml/main', globals())
manage_index_main=DTMLFile('dtml/index_main', globals())
manage_options=(
{'label':'Contents', 'action':'manage_main'},
)
isAnObjectManager=1
isPrincipiaFolderish=1
has_order_support = 0 # See OrderSupport.py
# IPossibleSite API
_components = None
security.declarePublic('getSiteManager')
def getSiteManager(self):
if self._components is None:
raise ComponentLookupError('No component registry defined.')
return self._components
security.declareProtected('Manage Site', 'setSiteManager')
def setSiteManager(self, components):
self._components = components
def __class_init__(self):
try: mt=list(self.meta_types)
except AttributeError: mt=[]
for b in self.__bases__:
try:
for t in b.meta_types:
if t not in mt: mt.append(t)
except AttributeError: pass
mt.sort()
self.meta_types=tuple(mt)
InitializeClass(self) # default__class_init__
def _verifyObjectPaste(self, object, validate_src=1):
# Verify whether the current user is allowed to paste the
# passed object into self. This is determined by checking
# to see if the user could create a new object of the same
# meta_type of the object passed in and checking that the
# user actually is allowed to access the passed in object
# in its existing context.
#
# Passing a false value for the validate_src argument will skip
# checking the passed in object in its existing context. This is
# mainly useful for situations where the passed in object has no
# existing context, such as checking an object during an import
# (the object will not yet have been connected to the acquisition
# heirarchy).
def absattr(attr):
if callable(attr): return attr()
return attr
if not hasattr(object, 'meta_type'):
raise CopyError(MessageDialog(
title = 'Not Supported',
message = ('The object <em>%s</em> does not support this' \
' operation' % escape(absattr(object.id))),
action = 'manage_main'))
if not hasattr(self, 'all_meta_types'):
raise CopyError(MessageDialog(
title = 'Not Supported',
message = 'Cannot paste into this object.',
action = 'manage_main'))
method_name = None
mt_permission = None
meta_types = absattr(self.all_meta_types)
for d in meta_types:
if d['name'] == object.meta_type:
method_name = d['action']
mt_permission = d.get('permission')
break
if mt_permission is not None:
sm = getSecurityManager()
if sm.checkPermission(mt_permission, self):
if validate_src:
# Ensure the user is allowed to access the object on the
# clipboard.
try:
parent = aq_parent(aq_inner(object))
except:
parent = None
if not sm.validate(None, parent, None, object):
raise Unauthorized(absattr(object.id))
if validate_src == 2: # moving
if not sm.checkPermission(delete_objects, parent):
raise Unauthorized('Delete not allowed.')
else:
raise CopyError(MessageDialog(
title = 'Insufficient Privileges',
message = ('You do not possess the %s permission in the '
'context of the container into which you are '
'pasting, thus you are not able to perform '
'this operation.' % mt_permission),
action = 'manage_main'))
else:
pass
#raise CopyError(MessageDialog(
# title = 'Not Supported',
# message = ('The object <em>%s</em> does not support this '
# 'operation.' % escape(absattr(object.id))),
# action = 'manage_main'))
# XXX(WORKFLOW): for some reason, this does not return meta_types
# like 'ERP5 Interaction', 'ERP5 Transition', ...
# so manage_renameObject (CopySupport.py) fails
# this is why we have the _verifyObjectPaste redefined above and ignoring
# CopyError
def all_meta_types(self, interfaces=None):
# A list of products registered elsewhere
import Products
external_candidates = []
# Look at _product_meta_types, if there is one
_pmt=()
if hasattr(self, '_product_meta_types'): _pmt=self._product_meta_types
elif hasattr(self, 'aq_acquire'):
try: _pmt=self.aq_acquire('_product_meta_types')
except: pass
external_candidates.extend(list(_pmt))
# Look at all globally visible meta types.
for entry in getattr(Products, 'meta_types', ()):
if ((interfaces is not None) or
(entry.get("visibility", None)=="Global")):
external_candidates.append(entry)
# Filter the list of external candidates based on the
# specified interface constraint
if interfaces is None:
interface_constrained_meta_types = external_candidates
else:
interface_constrained_meta_types = icmt = []
for entry in external_candidates:
try:
eil = entry.get('interfaces',None)
if eil is not None:
for ei in eil:
for i in interfaces:
if ei is i or ei.extends(i):
icmt.append(entry)
raise BreakoutException # only append 1ce
except BreakoutException:
pass
# Meta types specified by this instance are not checked against the
# interface constraint. This is as it always has been, but Im not
# sure it is correct.
interface_constrained_meta_types.extend(list(self.meta_types))
# Filter the list based on each meta-types's container_filter
meta_types = []
for entry in interface_constrained_meta_types:
container_filter = entry.get('container_filter',None)
if container_filter is None:
meta_types.append(entry)
else:
if container_filter(self):
meta_types.append(entry)
return meta_types
def _subobject_permissions(self):
return getPermissions()
def filtered_meta_types(self, user=None):
# Return a list of the types for which the user has
# adequate permission to add that type of object.
sm = getSecurityManager()
meta_types = []
if callable(self.all_meta_types):
all = self.all_meta_types()
else:
all = self.all_meta_types
for meta_type in all:
if 'permission' in meta_type:
if sm.checkPermission(meta_type['permission'], self):
meta_types.append(meta_type)
else:
meta_types.append(meta_type)
return meta_types
_checkId = checkValidId
def _setOb(self, id, object):
setattr(self, id, object)
def _delOb(self, id):
delattr(self, id)
def _getOb(self, id, default=_marker):
# FIXME: what we really need to do here is ensure that only
# sub-items are returned. That could have a measurable hit
# on performance as things are currently implemented, so for
# the moment we just make sure not to expose private attrs.
if id[:1] != '_' and hasattr(aq_base(self), id):
return getattr(self, id)
if default is _marker:
raise AttributeError, id
return default
security.declareProtected(access_contents_information, 'hasObject')
def hasObject(self, id):
"""Indicate whether the folder has an item by ID.
This doesn't try to be more intelligent than _getOb, and doesn't
consult _objects (for performance reasons). The common use case
is to check that an object does *not* exist.
"""
if (id in ('.', '..') or
id.startswith('_') or
id.startswith('aq_') or
id.endswith('__')):
return False
return getattr(aq_base(self), id, None) is not None
def _setObject(self, id, object, roles=None, user=None, set_owner=1,
suppress_events=False):
"""Set an object into this container.
Also sends IObjectWillBeAddedEvent and IObjectAddedEvent.
"""
ob = object # better name, keep original function signature
v = self._checkId(id)
if v is not None:
id = v
t = getattr(ob, 'meta_type', None)
# If an object by the given id already exists, remove it.
for object_info in self._objects:
if object_info['id'] == id:
self._delObject(id)
break
if not suppress_events:
notify(ObjectWillBeAddedEvent(ob, self, id))
self._objects = self._objects + ({'id': id, 'meta_type': t},)
self._setOb(id, ob)
ob = self._getOb(id)
if set_owner:
# TODO: eventify manage_fixupOwnershipAfterAdd
# This will be called for a copy/clone, or a normal _setObject.
ob.manage_fixupOwnershipAfterAdd()
# Try to give user the local role "Owner", but only if
# no local roles have been set on the object yet.
if getattr(ob, '__ac_local_roles__', _marker) is None:
user = getSecurityManager().getUser()
if user is not None:
userid = user.getId()
if userid is not None:
ob.manage_setLocalRoles(userid, ['Owner'])
if not suppress_events:
notify(ObjectAddedEvent(ob, self, id))
notifyContainerModified(self)
compatibilityCall('manage_afterAdd', ob, ob, self)
return id
def manage_afterAdd(self, item, container):
# Don't do recursion anymore, a subscriber does that.
pass
manage_afterAdd.__five_method__ = True
def manage_afterClone(self, item):
# Don't do recursion anymore, a subscriber does that.
pass
manage_afterClone.__five_method__ = True
def manage_beforeDelete(self, item, container):
# Don't do recursion anymore, a subscriber does that.
pass
manage_beforeDelete.__five_method__ = True
def _delObject(self, id, dp=1, suppress_events=False):
"""Delete an object from this container.
Also sends IObjectWillBeRemovedEvent and IObjectRemovedEvent.
"""
ob = self._getOb(id)
compatibilityCall('manage_beforeDelete', ob, ob, self)
if not suppress_events:
notify(ObjectWillBeRemovedEvent(ob, self, id))
self._objects = tuple([i for i in self._objects
if i['id'] != id])
self._delOb(id)
# Indicate to the object that it has been deleted. This is
# necessary for object DB mount points. Note that we have to
# tolerate failure here because the object being deleted could
# be a Broken object, and it is not possible to set attributes
# on Broken objects.
try:
ob._v__object_deleted__ = 1
except:
pass
if not suppress_events:
notify(ObjectRemovedEvent(ob, self, id))
notifyContainerModified(self)
security.declareProtected(access_contents_information, 'objectIds')
def objectIds(self, meta_type=None):
# Returns a list of subobject ids of the current object.
# If 'meta_type' is specified, returns objects whose meta_type
# matches 'meta_type'.
if meta_type is not None:
if type(meta_type) is str:
meta_type=[meta_type]
set=[]
for ob in self._objects:
if ob['meta_type'] in meta_type:
set.append(ob['id'])
return set
return [ o['id'] for o in self._objects ]
####################### modified methods ####################
# XXX(WORKFLOW): see all_meta_types
def manage_renameObject(self, id, new_id, REQUEST=None):
if getattr(self, new_id, None):
self._delObject(new_id)
return CopyContainer.manage_renameObject(self, id, new_id, REQUEST=REQUEST)
security.declareProtected(access_contents_information, 'objectValues')
# modified to be compatible with ERP5.Core.Folder parameters, so that
# it is possible to filter on portal_type, ...
def objectValues(self, spec=None, meta_type=None, portal_type=None,
sort_on=None, sort_order=None, checked_permission=None,
**kw):
# Returns list of objects contained in this folder.
# (no docstring to prevent publishing)
if meta_type is not None:
spec = meta_type
if self._folder_handler == OFS_HANDLER:
object_list = [ self._getOb(id) for id in self.objectIds(spec) ]
if portal_type is not None:
if isinstance(portal_type, str):
portal_type = (portal_type,)
object_list = filter(lambda x: x.getPortalType() in portal_type,
object_list)
if checked_permission is not None:
checkPermission = getSecurityManager().checkPermission
object_list = [o for o in object_list
if checkPermission(checked_permission, o)]
return sortValueList(object_list, sort_on, sort_order, **kw)
####################### end of modified methods ####################
####################### hacked method ####################
def _initBTrees(self):
pass
####################### end of hacked methods ####################
security.declareProtected(access_contents_information, 'objectItems')
def objectItems(self, spec=None):
# Returns a list of (id, subobject) tuples of the current object.
# If 'spec' is specified, returns only objects whose meta_type match
# 'spec'
return [ (id, self._getOb(id)) for id in self.objectIds(spec) ]
def objectMap(self):
# Return a tuple of mappings containing subobject meta-data
return tuple(d.copy() for d in self._objects)
security.declareProtected(access_contents_information, 'objectIds_d')
def objectIds_d(self, t=None):
if hasattr(self, '_reserved_names'): n=self._reserved_names
else: n=()
if not n: return self.objectIds(t)
r=[]
a=r.append
for id in self.objectIds(t):
if id not in n: a(id)
return r
security.declareProtected(access_contents_information, 'objectValues_d')
def objectValues_d(self, t=None):
return map(self._getOb, self.objectIds_d(t))
security.declareProtected(access_contents_information, 'objectItems_d')
def objectItems_d(self, t=None):
r=[]
a=r.append
g=self._getOb
for id in self.objectIds_d(t): a((id, g(id)))
return r
security.declareProtected(access_contents_information, 'objectMap_d')
def objectMap_d(self, t=None):
if hasattr(self, '_reserved_names'): n=self._reserved_names
else: n=()
if not n: return self._objects
r=[]
a=r.append
for d in self._objects:
if d['id'] not in n: a(d.copy())
return r
security.declareProtected(access_contents_information, 'superValues')
def superValues(self, t):
# Return all of the objects of a given type located in
# this object and containing objects.
if type(t) is str: t=(t,)
obj=self
seen={}
vals=[]
relativePhysicalPath = ()
x=0
while x < 100:
if not hasattr(obj,'_getOb'): break
get=obj._getOb
if hasattr(obj,'_objects'):
for i in obj._objects:
try:
id=i['id']
physicalPath = relativePhysicalPath + (id,)
if (physicalPath not in seen) and (i['meta_type'] in t):
vals.append(get(id))
seen[physicalPath]=1
except: pass
if hasattr(obj,'aq_parent'):
obj=obj.aq_parent
relativePhysicalPath = ('..',) + relativePhysicalPath
else:
return vals
x=x+1
return vals
manage_addProduct = ProductDispatcher()
security.declareProtected(delete_objects, 'manage_delObjects')
def manage_delObjects(self, ids=[], REQUEST=None):
"""Delete a subordinate object
The objects specified in 'ids' get deleted.
"""
if type(ids) is str: ids=[ids]
if not ids:
return MessageDialog(title='No items specified',
message='No items were specified!',
action ='./manage_main',)
try: p=self._reserved_names
except: p=()
for n in ids:
if n in p:
return MessageDialog(title='Not Deletable',
message='<EM>%s</EM> cannot be deleted.' % escape(n),
action ='./manage_main',)
while ids:
id=ids[-1]
v=self._getOb(id, self)
if v.wl_isLocked():
raise ResourceLockedError, (
'Object "%s" is locked via WebDAV' % v.getId())
if v is self:
raise BadRequest, '%s does not exist' % escape(ids[-1])
self._delObject(id)
del ids[-1]
if REQUEST is not None:
return self.manage_main(self, REQUEST, update_menu=1)
security.declareProtected(access_contents_information, 'tpValues')
def tpValues(self):
# Return a list of subobjects, used by tree tag.
r=[]
if hasattr(aq_base(self), 'tree_ids'):
tree_ids=self.tree_ids
try: tree_ids=list(tree_ids)
except TypeError:
pass
if hasattr(tree_ids, 'sort'):
tree_ids.sort()
for id in tree_ids:
if hasattr(self, id):
r.append(self._getOb(id))
else:
obj_ids=self.objectIds()
obj_ids.sort()
for id in obj_ids:
o=self._getOb(id)
if hasattr(aq_base(o), 'isPrincipiaFolderish') and \
o.isPrincipiaFolderish:
r.append(o)
return r
security.declareProtected(import_export_objects, 'manage_exportObject')
def manage_exportObject(self, id='', download=None, toxml=None,
RESPONSE=None,REQUEST=None):
"""Exports an object to a file and returns that file."""
if not id:
# can't use getId() here (breaks on "old" exported objects)
id=self.id
if hasattr(id, 'im_func'): id=id()
ob=self
else: ob=self._getOb(id)
suffix=toxml and 'xml' or 'zexp'
if download:
f=StringIO()
if toxml:
exportXML(ob._p_jar, ob._p_oid, f)
else:
ob._p_jar.exportFile(ob._p_oid, f)
if RESPONSE is not None:
RESPONSE.setHeader('Content-type','application/data')
RESPONSE.setHeader('Content-Disposition',
'inline;filename=%s.%s' % (id, suffix))
return f.getvalue()
cfg = getConfiguration()
f = os.path.join(cfg.clienthome, '%s.%s' % (id, suffix))
if toxml:
exportXML(ob._p_jar, ob._p_oid, f)
else:
ob._p_jar.exportFile(ob._p_oid, f)
if REQUEST is not None:
return self.manage_main(self, REQUEST,
manage_tabs_message=
'<em>%s</em> successfully exported to <em>%s</em>' % (id,f),
title = 'Object exported')
security.declareProtected(import_export_objects, 'manage_importExportForm')
manage_importExportForm=DTMLFile('dtml/importExport',globals())
security.declareProtected(import_export_objects, 'manage_importObject')
def manage_importObject(self, file, REQUEST=None, set_owner=1):
"""Import an object from a file"""
dirname, file=os.path.split(file)
if dirname:
raise BadRequest, 'Invalid file name %s' % escape(file)
for impath in self._getImportPaths():
filepath = os.path.join(impath, 'import', file)
if os.path.exists(filepath):
break
else:
raise BadRequest, 'File does not exist: %s' % escape(file)
self._importObjectFromFile(filepath, verify=not not REQUEST,
set_owner=set_owner)
if REQUEST is not None:
return self.manage_main(
self, REQUEST,
manage_tabs_message='<em>%s</em> successfully imported' % id,
title='Object imported',
update_menu=1)
def _importObjectFromFile(self, filepath, verify=1, set_owner=1):
# locate a valid connection
connection=self._p_jar
obj=self
while connection is None:
obj=obj.aq_parent
connection=obj._p_jar
ob=connection.importFile(
filepath, customImporters=customImporters)
if verify: self._verifyObjectPaste(ob, validate_src=0)
id=ob.id
if hasattr(id, 'im_func'): id=id()
self._setObject(id, ob, set_owner=set_owner)
# try to make ownership implicit if possible in the context
# that the object was imported into.
ob=self._getOb(id)
ob.manage_changeOwnershipType(explicit=0)
def _getImportPaths(self):
cfg = getConfiguration()
paths = []
zopehome = getattr(cfg, 'zopehome', None)
if zopehome is not None and cfg.zopehome is not None:
paths.append(zopehome)
if not cfg.instancehome in paths:
paths.append(cfg.instancehome)
if not cfg.clienthome in paths:
paths.append(cfg.clienthome)
return paths
def list_imports(self):
listing = []
for impath in self._getImportPaths():
directory = os.path.join(impath, 'import')
if not os.path.isdir(directory):
continue
listing += [f for f in os.listdir(directory)
if f.endswith('.zexp') or f.endswith('.xml')]
listing.sort()
return listing
# FTP support methods
security.declareProtected(ftp_access, 'manage_FTPlist')
def manage_FTPlist(self, REQUEST):
"""Directory listing for FTP.
"""
out=()
# check to see if we are being acquiring or not
ob=self
while 1:
if is_acquired(ob):
raise ValueError('FTP List not supported on acquired objects')
if not hasattr(ob,'aq_parent'):
break
ob=ob.aq_parent
files = list(self.objectItems())
# recursive ride through all subfolders (ls -R) (ajung)
if REQUEST.environ.get('FTP_RECURSIVE',0) == 1:
all_files = copy.copy(files)
for f in files:
if (hasattr(aq_base(f[1]), 'isPrincipiaFolderish') and
f[1].isPrincipiaFolderish):
all_files.extend(findChildren(f[1]))
files = all_files
# Perform globbing on list of files (ajung)
globbing = REQUEST.environ.get('GLOBBING','')
if globbing :
files = [x for x in files if fnmatch.fnmatch(x[0],globbing)]
files.sort()
if not (hasattr(self,'isTopLevelPrincipiaApplicationObject') and
self.isTopLevelPrincipiaApplicationObject):
files.insert(0,('..',self.aq_parent))
files.insert(0, ('.', self))
for k,v in files:
# Note that we have to tolerate failure here, because
# Broken objects won't stat correctly. If an object fails
# to be able to stat itself, we will ignore it, but log
# the error.
try:
stat=marshal.loads(v.manage_FTPstat(REQUEST))
except:
LOG.error("Failed to stat file '%s'" % k,
exc_info=sys.exc_info())
stat=None
if stat is not None:
out=out+((k,stat),)
return marshal.dumps(out)
security.declareProtected(ftp_access, 'manage_hasId')
def manage_hasId(self, REQUEST):
""" check if the folder has an object with REQUEST['id'] """
if not REQUEST['id'] in self.objectIds():
raise KeyError(REQUEST['id'])
security.declareProtected(ftp_access, 'manage_FTPstat')
def manage_FTPstat(self,REQUEST):
"""Psuedo stat, used by FTP for directory listings.
"""
mode=0040000
from AccessControl.User import nobody
# check to see if we are acquiring our objectValues or not
if not (len(REQUEST.PARENTS) > 1 and
self.objectValues() == REQUEST.PARENTS[1].objectValues()):
try:
if getSecurityManager().validate(
None, self, 'manage_FTPlist', self.manage_FTPlist
):
mode=mode | 0770
except: pass
if nobody.allowed(
self,
getRoles(self, 'manage_FTPlist', self.manage_FTPlist, ())):
mode=mode | 0007
mtime=self.bobobase_modification_time().timeTime()
# get owner and group
owner=group='Zope'
for user, roles in self.get_local_roles():
if 'Owner' in roles:
owner=user
break
return marshal.dumps((mode,0,0,1,owner,group,0,mtime,mtime,mtime))
def __delitem__(self, name):
return self.manage_delObjects(ids=[name])
def __getitem__(self, key):
if key in self:
return self._getOb(key, None)
request = getattr(self, 'REQUEST', None)
if not isinstance(request, (str, NoneType)):
method=request.get('REQUEST_METHOD', 'GET')
if (request.maybe_webdav_client and
method not in ('GET', 'POST')):
return NullResource(self, key, request).__of__(self)
raise KeyError, key
def __setitem__(self, key, value):
return self._setObject(key, value)
def __contains__(self, name):
return name in self.objectIds()
def __iter__(self):
return iter(self.objectIds())
def __len__(self):
return len(self.objectIds())
def __nonzero__(self):
return True
security.declareProtected(access_contents_information, 'get')
def get(self, key, default=None):
if key in self:
return self._getOb(key, default)
return default
security.declareProtected(access_contents_information, 'keys')
def keys(self):
return self.objectIds()
security.declareProtected(access_contents_information, 'items')
def items(self):
return self.objectItems()
security.declareProtected(access_contents_information, 'values')
def values(self):
return self.objectValues()
# Don't InitializeClass, there is a specific __class_init__ on ObjectManager
# InitializeClass(ObjectManager)
def findChildren(obj,dirname=''):
""" recursive walk through the object hierarchy to
find all children of an object (ajung)
"""
lst = []
for name, child in obj.objectItems():
if (hasattr(aq_base(child), 'isPrincipiaFolderish') and
child.isPrincipiaFolderish):
lst.extend(findChildren(child, dirname + obj.id + '/'))
else:
lst.append((dirname + obj.id + "/" + name, child))
return lst
from Products.ERP5Type.Utils import sortValueList
from Products.ERP5Type.Globals import Persistent, PersistentMapping
from Products.ERP5Type import Permissions
from AccessControl import ClassSecurityInfo
from AccessControl import getSecurityManager
from App.special_dtml import DTMLFile
from zope.event import notify
from OFS.event import ObjectWillBeAddedEvent
from OFS.subscribers import compatibilityCall
from zope.lifecycleevent import ObjectAddedEvent
from zope.lifecycleevent import ObjectRemovedEvent
from zope.container.contained import notifyContainerModified
from OFS.Folder import Folder
from Products.CMFCore.PortalFolder import PortalFolderBase
from Products.ERP5Type.Base import Base
from zLOG import LOG
_marker=[]
class ERP5PersistentMappingFolder(PortalFolderBase):
meta_type = 'ERP5 Persistent Mapping Folder'
portal_type = 'ERP5PersistentMappingFolder'
_object_dict = None
# Declarative security
security = ClassSecurityInfo()
security.declareProtected(Permissions.ViewManagementScreens, 'manage_main')
manage_main = DTMLFile('contents', globals())
def __init__(self, id, title=''):
PortalFolderBase.__init__(self, id, title)
self._object_dict = PersistentMapping()
def __getattr__(self, name):
if self._object_dict is None:
LOG("### self._object_dict is None", 0, '')
raise AttributeError(name)
try:
return self._object_dict[name]
except KeyError:
LOG("### KeyError for key " + name + " not in:", 0, self._object_dict)
raise AttributeError(name)
def __len__(self):
return self.objectCount()
security.declareProtected(Permissions.AccessContentsInformation, 'get')
def get(self, name, default=None):
return self._getOb(name, default)
def __getitem__(self, name):
return self._getOb(name)
def _setOb(self, object_id, object_value):
if self._object_dict is None:
self._object_dict = PersistentMapping()
self._object_dict[object_id] = object_value
def _delOb(self, object_id):
del self._object_dict[object_id]
def _getOb(self, object_id, default=_marker):
"""
Return the named object from the folder.
"""
try:
return self._object_dict[object_id].__of__(self)
except KeyError:
if default is _marker:
raise
else:
return default
def objectIds(self, spec=None, **kw):
# we don't plan to use meta_type now, so spec is just here for compatibility
assert(spec is None)
return self._object_dict.keys()
def objectCount(self):
return len(self._object_dict)
def objectItems(self, spec=None):
assert(spec is None)
return self._object_dict
def objectIds_d(self, t=None):
assert(t is None)
return objectIds(self, t)
security.declareProtected( Permissions.AccessContentsInformation,
'objectValues' )
def objectValues(self, spec=None, portal_type=None, sort_on=None,
sort_order=None, checked_permission=None, **kw):
# Returns list of objects contained in this folder.
# (no docstring to prevent publishing)
assert(spec is None)
if self._object_dict is None:
return []
object_list = self._object_dict.values()
if portal_type is not None:
if isinstance(portal_type, str):
portal_type = (portal_type,)
object_list = filter(lambda x: x.getPortalType() in portal_type,
object_list)
if checked_permission is not None:
checkPermission = getSecurityManager().checkPermission
object_list = [o for o in object_list
if checkPermission(checked_permission, o)]
return sortValueList(object_list, sort_on, sort_order, **kw)
security.declareProtected(Permissions.AccessContentsInformation,
'keys', 'items', 'values')
keys = objectIds
values = objectValues
items = objectItems
def _setObject(self, id, object, roles=None, user=None, set_owner=True,
suppress_events=False):
ob = object # better name, keep original function signature
v = self._checkId(id)
if v is not None:
id = v
# If an object by the given id already exists, remove it.
if id in self:
self._delObject(id)
if not suppress_events:
notify(ObjectWillBeAddedEvent(ob, self, id))
self._setOb(id, ob)
ob = self._getOb(id)
if set_owner:
# TODO: eventify manage_fixupOwnershipAfterAdd
# This will be called for a copy/clone, or a normal _setObject.
ob.manage_fixupOwnershipAfterAdd()
# Try to give user the local role "Owner", but only if
# no local roles have been set on the object yet.
if getattr(ob, '__ac_local_roles__', _marker) is None:
user = getSecurityManager().getUser()
if user is not None:
userid = user.getId()
if userid is not None:
ob.manage_setLocalRoles(userid, ['Owner'])
if not suppress_events:
notify(ObjectAddedEvent(ob, self, id))
notifyContainerModified(self)
compatibilityCall('manage_afterAdd', ob, ob, self)
return id
def _cleanup(self):
cleaned = False
for attribute in ('_tree', '_mt_index', '_count'):
try:
if object.__getattribute__(self, attribute):
del self._tree
cleaned = True
except AttributeError:
pass
return cleaned
def has_key(self, key):
if (key in ('.', '..') or
key.startswith('_') or
key.startswith('aq_') or
key.endswith('__') or
self._object_dict is None):
return False
return self._object_dict.get(key, None) is not None
hasObject = has_key
def hashId(self, id):
raise NotImplementedError
def _populateFromFolder(self, source):
"""Fill this folder with the contents of another folder.
"""
for name in source.objectIds():
value = source._getOb(name, None)
if value is not None:
self._setOb(name, aq_base(value))
def tpValues(self):
"""
Ensures the items don't show up in the left pane.
"""
# is this really useful?
return ()
def _checkId(self, id, allow_dup=0):
if self._object_dict is not None and not allow_dup and id in self._object_dict:
raise BadRequestException('The id "%s" is invalid--'
'it is already in use.' % id)
from ERP5PersistentMappingFolder import ERP5PersistentMappingFolder
from Products.ERP5Type.Globals import PersistentMapping
from Products.ERP5Type.Utils import sortValueList
from Products.ERP5Type import Permissions
from AccessControl import ClassSecurityInfo
class ERP5PersistentMappingIndexFolder(ERP5PersistentMappingFolder):
meta_type = 'ERP5 Persistent Mapping Index Folder'
portal_type = 'ERP5PersistentMappingIndexFolder'
# Declarative security
security = ClassSecurityInfo()
security.declareObjectProtected(Permissions.AccessContentsInformation)
def __init__(self):
ERP5PersistentMappingFolder.__init__(self)
self._object_index = PersistentMapping()
def _setOb(self, object_id, object_value):
self._object_dict[object_id] = object_value
self._object_index[object_id] = {'portal_type': object_value.getPortalType()}
def _delOb(self, object_id):
del self._object_dict[object_id]
del self._object_index[object_id]
security.declareProtected( Permissions.AccessContentsInformation,
'objectValues' )
def objectValues(self, spec=None, meta_type=None, portal_type=None,
sort_on=None, sort_order=None, checked_permission=None,
**kw):
# Returns list of objects contained in this folder.
# (no docstring to prevent publishing)
if meta_type is not None:
raise NotImplementedError
object_list = self._object_dict.values()
if portal_type is not None:
if isinstance(portal_type, str):
portal_type = (portal_type,)
object_list = [self._object_dict[key] for key in self._object_dict.keys()
if self._object_index[key]['portal_type'] in portal_type]
if checked_permission is not None:
checkPermission = getSecurityManager().checkPermission
object_list = [o for o in object_list
if checkPermission(checked_permission, o)]
return sortValueList(object_list, sort_on, sort_order, **kw)
...@@ -73,6 +73,7 @@ except ImportError: ...@@ -73,6 +73,7 @@ except ImportError:
class HBTreeFolder2: class HBTreeFolder2:
pass pass
from ERP5PersistentMappingFolder import ERP5PersistentMappingFolder
from DateTime import DateTime from DateTime import DateTime
from random import randint from random import randint
...@@ -536,10 +537,12 @@ class FolderMixIn(ExtensionClass.Base): ...@@ -536,10 +537,12 @@ class FolderMixIn(ExtensionClass.Base):
OFS_HANDLER = 0 OFS_HANDLER = 0
BTREE_HANDLER = 1 BTREE_HANDLER = 1
HBTREE_HANDLER = 2 HBTREE_HANDLER = 2
PERSISTENT_MAPPING_HANDLER = 3
InitializeClass(FolderMixIn) InitializeClass(FolderMixIn)
class Folder(CopyContainer, CMFBTreeFolder, CMFHBTreeFolder, Base, FolderMixIn): class Folder(CopyContainer, CMFBTreeFolder, CMFHBTreeFolder,
ERP5PersistentMappingFolder, Base, FolderMixIn):
""" """
A Folder is a subclass of Base but not of XMLObject. A Folder is a subclass of Base but not of XMLObject.
Folders are not considered as documents and are therefore Folders are not considered as documents and are therefore
...@@ -606,12 +609,14 @@ class Folder(CopyContainer, CMFBTreeFolder, CMFHBTreeFolder, Base, FolderMixIn): ...@@ -606,12 +609,14 @@ class Folder(CopyContainer, CMFBTreeFolder, CMFHBTreeFolder, Base, FolderMixIn):
description = None description = None
# Per default we use BTree folder # Per default we use BTree folder
_folder_handler = BTREE_HANDLER _folder_handler = PERSISTENT_MAPPING_HANDLER
# Overload __init__ so that we do not take into account title # Overload __init__ so that we do not take into account title
# This is required for test_23_titleIsNotDefinedByDefault # This is required for test_23_titleIsNotDefinedByDefault
def __init__(self, id): def __init__(self, id):
self.id = id self.id = id
if self._folder_handler == PERSISTENT_MAPPING_HANDLER:
ERP5PersistentMappingFolder.__init__(self, id)
security.declarePublic('newContent') security.declarePublic('newContent')
def newContent(self, *args, **kw): def newContent(self, *args, **kw):
...@@ -736,13 +741,17 @@ class Folder(CopyContainer, CMFBTreeFolder, CMFHBTreeFolder, Base, FolderMixIn): ...@@ -736,13 +741,17 @@ class Folder(CopyContainer, CMFBTreeFolder, CMFHBTreeFolder, Base, FolderMixIn):
def _initBTrees(self): def _initBTrees(self):
if self._folder_handler == HBTREE_HANDLER: if self._folder_handler == HBTREE_HANDLER:
return CMFHBTreeFolder._initBTrees(self) return CMFHBTreeFolder._initBTrees(self)
else: elif self._folder_handler == BTREE_HANDLER:
return CMFBTreeFolder._initBTrees(self) return CMFBTreeFolder._initBTrees(self)
else:
raise NotImplementedError
def hashId(self, id): def hashId(self, id):
"""Return a hash of id """Return a hash of id
""" """
if self._folder_handler == HBTREE_HANDLER: if self._folder_handler == PERSISTENT_MAPPING_HANDLER:
return ERP5PersistentMappingFolder.hashId(self, id)
elif self._folder_handler == HBTREE_HANDLER:
return CMFHBTreeFolder.hashId(self, id) return CMFHBTreeFolder.hashId(self, id)
else: else:
return CMFBTreeFolder.hashId(self, id) return CMFBTreeFolder.hashId(self, id)
...@@ -750,7 +759,9 @@ class Folder(CopyContainer, CMFBTreeFolder, CMFHBTreeFolder, Base, FolderMixIn): ...@@ -750,7 +759,9 @@ class Folder(CopyContainer, CMFBTreeFolder, CMFHBTreeFolder, Base, FolderMixIn):
def _populateFromFolder(self, source): def _populateFromFolder(self, source):
"""Fill this folder with the contents of another folder. """Fill this folder with the contents of another folder.
""" """
if self._folder_handler == HBTREE_HANDLER: if self._folder_handler == PERSISTENT_MAPPING_HANDLER:
return ERP5PersistentMappingFolder._populateFromFolder(self, source)
elif self._folder_handler == HBTREE_HANDLER:
if self._htree is None: if self._htree is None:
HBTreeFolder2Base.__init__(self, id) HBTreeFolder2Base.__init__(self, id)
return CMFHBTreeFolder._populateFromFolder(self, source) return CMFHBTreeFolder._populateFromFolder(self, source)
...@@ -762,13 +773,17 @@ class Folder(CopyContainer, CMFBTreeFolder, CMFHBTreeFolder, Base, FolderMixIn): ...@@ -762,13 +773,17 @@ class Folder(CopyContainer, CMFBTreeFolder, CMFHBTreeFolder, Base, FolderMixIn):
def manage_fixCount(self): def manage_fixCount(self):
"""Calls self._fixCount() and reports the result as text. """Calls self._fixCount() and reports the result as text.
""" """
if self._folder_handler == HBTREE_HANDLER: if self._folder_handler == PERSISTENT_MAPPING_HANDLER:
raise NotImplementedError
elif self._folder_handler == HBTREE_HANDLER:
return CMFHBTreeFolder.manage_fixCount(self) return CMFHBTreeFolder.manage_fixCount(self)
else: else:
return CMFBTreeFolder.manage_fixCount(self) return CMFBTreeFolder.manage_fixCount(self)
def _fixCount(self): def _fixCount(self):
if self._folder_handler == HBTREE_HANDLER: if self._folder_handler == PERSISTENT_MAPPING_HANDLER:
raise NotImplementedError
elif self._folder_handler == HBTREE_HANDLER:
return CMFHBTreeFolder._fixCount(self) return CMFHBTreeFolder._fixCount(self)
else: else:
return CMFBTreeFolder._fixCount(self) return CMFBTreeFolder._fixCount(self)
...@@ -791,7 +806,9 @@ class Folder(CopyContainer, CMFBTreeFolder, CMFHBTreeFolder, Base, FolderMixIn): ...@@ -791,7 +806,9 @@ class Folder(CopyContainer, CMFBTreeFolder, CMFHBTreeFolder, Base, FolderMixIn):
def manage_cleanup(self): def manage_cleanup(self):
"""Calls self._cleanup() and reports the result as text. """Calls self._cleanup() and reports the result as text.
""" """
if self._folder_handler == HBTREE_HANDLER: if self._folder_handler == PERSISTENT_MAPPING_HANDLER:
raise NotImplementedError
elif self._folder_handler == HBTREE_HANDLER:
if self._htree is None: if self._htree is None:
return 1 return 1
else: else:
...@@ -803,7 +820,9 @@ class Folder(CopyContainer, CMFBTreeFolder, CMFHBTreeFolder, Base, FolderMixIn): ...@@ -803,7 +820,9 @@ class Folder(CopyContainer, CMFBTreeFolder, CMFHBTreeFolder, Base, FolderMixIn):
return CMFBTreeFolder.manage_cleanup(self) return CMFBTreeFolder.manage_cleanup(self)
def _cleanup(self): def _cleanup(self):
if self._folder_handler == HBTREE_HANDLER: if self._folder_handler == PERSISTENT_MAPPING_HANDLER:
return ERP5PersistentMappingFolder._cleanup(self)
elif self._folder_handler == HBTREE_HANDLER:
if self._htree is None: if self._htree is None:
return 1 return 1
else: else:
...@@ -818,7 +837,9 @@ class Folder(CopyContainer, CMFBTreeFolder, CMFHBTreeFolder, Base, FolderMixIn): ...@@ -818,7 +837,9 @@ class Folder(CopyContainer, CMFBTreeFolder, CMFHBTreeFolder, Base, FolderMixIn):
""" """
Return the named object from the folder. Return the named object from the folder.
""" """
if self._folder_handler == HBTREE_HANDLER: if self._folder_handler == PERSISTENT_MAPPING_HANDLER:
return ERP5PersistentMappingFolder._getOb(self, id, *args, **kw)
elif self._folder_handler == HBTREE_HANDLER:
if self._htree is None: if self._htree is None:
if len(args): if len(args):
return args[0] return args[0]
...@@ -840,7 +861,9 @@ class Folder(CopyContainer, CMFBTreeFolder, CMFHBTreeFolder, Base, FolderMixIn): ...@@ -840,7 +861,9 @@ class Folder(CopyContainer, CMFBTreeFolder, CMFHBTreeFolder, Base, FolderMixIn):
def _setOb(self, id, object): def _setOb(self, id, object):
"""Store the named object in the folder. """Store the named object in the folder.
""" """
if self._folder_handler == HBTREE_HANDLER: if self._folder_handler == PERSISTENT_MAPPING_HANDLER:
return ERP5PersistentMappingFolder._setOb(self, id, object)
elif self._folder_handler == HBTREE_HANDLER:
if self._htree is None: if self._htree is None:
HBTreeFolder2Base.__init__(self, self.id) HBTreeFolder2Base.__init__(self, self.id)
return CMFHBTreeFolder._setOb(self, id, object) return CMFHBTreeFolder._setOb(self, id, object)
...@@ -852,7 +875,9 @@ class Folder(CopyContainer, CMFBTreeFolder, CMFHBTreeFolder, Base, FolderMixIn): ...@@ -852,7 +875,9 @@ class Folder(CopyContainer, CMFBTreeFolder, CMFHBTreeFolder, Base, FolderMixIn):
def _delOb(self, id): def _delOb(self, id):
"""Remove the named object from the folder. """Remove the named object from the folder.
""" """
if self._folder_handler == HBTREE_HANDLER: if self._folder_handler == PERSISTENT_MAPPING_HANDLER:
return ERP5PersistentMappingFolder._delOb(self, id)
elif self._folder_handler == HBTREE_HANDLER:
return CMFHBTreeFolder._delOb(self, id) return CMFHBTreeFolder._delOb(self, id)
else: else:
return CMFBTreeFolder._delOb(self, id) return CMFBTreeFolder._delOb(self, id)
...@@ -860,7 +885,9 @@ class Folder(CopyContainer, CMFBTreeFolder, CMFHBTreeFolder, Base, FolderMixIn): ...@@ -860,7 +885,9 @@ class Folder(CopyContainer, CMFBTreeFolder, CMFHBTreeFolder, Base, FolderMixIn):
def getBatchObjectListing(self, REQUEST=None): def getBatchObjectListing(self, REQUEST=None):
"""Return a structure for a page template to show the list of objects. """Return a structure for a page template to show the list of objects.
""" """
if self._folder_handler == HBTREE_HANDLER: if self._folder_handler == PERSISTENT_MAPPING_HANDLER:
raise NotImplementedError
elif self._folder_handler == HBTREE_HANDLER:
return CMFHBTreeFolder.getBatchObjectListing(self, REQUEST) return CMFHBTreeFolder.getBatchObjectListing(self, REQUEST)
else: else:
return CMFBTreeFolder.getBatchObjectListing(self, REQUEST) return CMFBTreeFolder.getBatchObjectListing(self, REQUEST)
...@@ -868,14 +895,18 @@ class Folder(CopyContainer, CMFBTreeFolder, CMFHBTreeFolder, Base, FolderMixIn): ...@@ -868,14 +895,18 @@ class Folder(CopyContainer, CMFBTreeFolder, CMFHBTreeFolder, Base, FolderMixIn):
def manage_object_workspace(self, ids=(), REQUEST=None): def manage_object_workspace(self, ids=(), REQUEST=None):
'''Redirects to the workspace of the first object in '''Redirects to the workspace of the first object in
the list.''' the list.'''
if self._folder_handler == HBTREE_HANDLER: if self._folder_handler == PERSISTENT_MAPPING_HANDLER:
raise NotImplementedError
elif self._folder_handler == HBTREE_HANDLER:
return CMFHBTreeFolder.manage_object_workspace(self, ids, REQUEST) return CMFHBTreeFolder.manage_object_workspace(self, ids, REQUEST)
else: else:
return CMFBTreeFolder.manage_object_workspace(self, ids, REQUEST) return CMFBTreeFolder.manage_object_workspace(self, ids, REQUEST)
def manage_main(self, *args, **kw): def manage_main(self, *args, **kw):
''' List content.''' ''' List content.'''
if self._folder_handler == HBTREE_HANDLER: if self._folder_handler == PERSISTENT_MAPPING_HANDLER:
return ERP5PersistentMappingFolder.manage_main.__of__(self)(self, *args, **kw)
elif self._folder_handler == HBTREE_HANDLER:
return CMFHBTreeFolder.manage_main.__of__(self)(self, *args, **kw) return CMFHBTreeFolder.manage_main.__of__(self)(self, *args, **kw)
else: else:
return CMFBTreeFolder.manage_main.__of__(self)(self, *args, **kw) return CMFBTreeFolder.manage_main.__of__(self)(self, *args, **kw)
...@@ -883,14 +914,18 @@ class Folder(CopyContainer, CMFBTreeFolder, CMFHBTreeFolder, Base, FolderMixIn): ...@@ -883,14 +914,18 @@ class Folder(CopyContainer, CMFBTreeFolder, CMFHBTreeFolder, Base, FolderMixIn):
def tpValues(self): def tpValues(self):
"""Ensures the items don't show up in the left pane. """Ensures the items don't show up in the left pane.
""" """
if self._folder_handler == HBTREE_HANDLER: if self._folder_handler == PERSISTENT_MAPPING_HANDLER:
return ERP5PersistentMappingFolder.tpValues(self)
elif self._folder_handler == HBTREE_HANDLER:
return CMFHBTreeFolder.tpValues(self) return CMFHBTreeFolder.tpValues(self)
else: else:
return CMFBTreeFolder.tpValues(self) return CMFBTreeFolder.tpValues(self)
def objectCount(self): def objectCount(self):
"""Returns the number of items in the folder.""" """Returns the number of items in the folder."""
if self._folder_handler == HBTREE_HANDLER: if self._folder_handler == PERSISTENT_MAPPING_HANDLER:
return ERP5PersistentMappingFolder.objectCount(self)
elif self._folder_handler == HBTREE_HANDLER:
if self._htree is None: if self._htree is None:
return 0 return 0
return CMFHBTreeFolder.objectCount(self) return CMFHBTreeFolder.objectCount(self)
...@@ -902,7 +937,9 @@ class Folder(CopyContainer, CMFBTreeFolder, CMFHBTreeFolder, Base, FolderMixIn): ...@@ -902,7 +937,9 @@ class Folder(CopyContainer, CMFBTreeFolder, CMFHBTreeFolder, Base, FolderMixIn):
def has_key(self, id): def has_key(self, id):
"""Indicates whether the folder has an item by ID. """Indicates whether the folder has an item by ID.
""" """
if self._folder_handler == HBTREE_HANDLER: if self._folder_handler == PERSISTENT_MAPPING_HANDLER:
return ERP5PersistentMappingFolder.has_key(self, id)
elif self._folder_handler == HBTREE_HANDLER:
if self._htree is None: if self._htree is None:
return False return False
return CMFHBTreeFolder.has_key(self, id) return CMFHBTreeFolder.has_key(self, id)
...@@ -914,13 +951,17 @@ class Folder(CopyContainer, CMFBTreeFolder, CMFHBTreeFolder, Base, FolderMixIn): ...@@ -914,13 +951,17 @@ class Folder(CopyContainer, CMFBTreeFolder, CMFHBTreeFolder, Base, FolderMixIn):
def getTreeIdList(self, htree=None): def getTreeIdList(self, htree=None):
""" recursively build a list of btree ids """ recursively build a list of btree ids
""" """
if self._folder_handler == HBTREE_HANDLER: if self._folder_handler == PERSISTENT_MAPPING_HANDLER:
raise NotImplementedError
elif self._folder_handler == HBTREE_HANDLER:
return CMFHBTreeFolder.getTreeIdList(self, htree) return CMFHBTreeFolder.getTreeIdList(self, htree)
else: else:
return CMFBTreeFolder.getTreeIdList(self, htree) return CMFBTreeFolder.getTreeIdList(self, htree)
def objectIds(self, spec=None, **kw): def objectIds(self, spec=None, **kw):
if self._folder_handler == HBTREE_HANDLER: if self._folder_handler == PERSISTENT_MAPPING_HANDLER:
return ERP5PersistentMappingFolder.objectIds(self, spec=spec, **kw)
elif self._folder_handler == HBTREE_HANDLER:
if self._htree is None: if self._htree is None:
return [] return []
assert spec is None assert spec is None
...@@ -934,7 +975,9 @@ class Folder(CopyContainer, CMFBTreeFolder, CMFHBTreeFolder, Base, FolderMixIn): ...@@ -934,7 +975,9 @@ class Folder(CopyContainer, CMFBTreeFolder, CMFHBTreeFolder, Base, FolderMixIn):
return CMFBTreeFolder.objectIds(self, spec) return CMFBTreeFolder.objectIds(self, spec)
def objectItems(self, spec=None, **kw): def objectItems(self, spec=None, **kw):
if self._folder_handler == HBTREE_HANDLER: if self._folder_handler == PERSISTENT_MAPPING_HANDLER:
return ERP5PersistentMappingFolder.objectItems(self, spec=spec)
elif self._folder_handler == HBTREE_HANDLER:
if self._htree is None: if self._htree is None:
return [] return []
assert spec is None assert spec is None
...@@ -948,7 +991,9 @@ class Folder(CopyContainer, CMFBTreeFolder, CMFHBTreeFolder, Base, FolderMixIn): ...@@ -948,7 +991,9 @@ class Folder(CopyContainer, CMFBTreeFolder, CMFHBTreeFolder, Base, FolderMixIn):
return CMFBTreeFolder.objectItems(self, spec) return CMFBTreeFolder.objectItems(self, spec)
def objectIds_d(self, t=None): def objectIds_d(self, t=None):
if self._folder_handler == HBTREE_HANDLER: if self._folder_handler == PERSISTENT_MAPPING_HANDLER:
return ERP5PersistentMappingFolder.objectIds_d(self, t)
elif self._folder_handler == HBTREE_HANDLER:
if self._htree is None: if self._htree is None:
return {} return {}
return CMFHBTreeFolder.objectIds_d(self, t) return CMFHBTreeFolder.objectIds_d(self, t)
...@@ -958,13 +1003,17 @@ class Folder(CopyContainer, CMFBTreeFolder, CMFHBTreeFolder, Base, FolderMixIn): ...@@ -958,13 +1003,17 @@ class Folder(CopyContainer, CMFBTreeFolder, CMFHBTreeFolder, Base, FolderMixIn):
return CMFBTreeFolder.objectIds_d(self, t) return CMFBTreeFolder.objectIds_d(self, t)
def _checkId(self, id, allow_dup=0): def _checkId(self, id, allow_dup=0):
if self._folder_handler == HBTREE_HANDLER: if self._folder_handler == PERSISTENT_MAPPING_HANDLER:
return ERP5PersistentMappingFolder._checkId(self, id ,allow_dup)
elif self._folder_handler == HBTREE_HANDLER:
return CMFHBTreeFolder._checkId(self, id, allow_dup) return CMFHBTreeFolder._checkId(self, id, allow_dup)
else: else:
return CMFBTreeFolder._checkId(self, id, allow_dup) return CMFBTreeFolder._checkId(self, id, allow_dup)
def _setObject(self, *args, **kw): def _setObject(self, *args, **kw):
if self._folder_handler == HBTREE_HANDLER: if self._folder_handler == PERSISTENT_MAPPING_HANDLER:
return ERP5PersistentMappingFolder._setObject(self, *args, **kw)
elif self._folder_handler == HBTREE_HANDLER:
if self._htree is None: if self._htree is None:
HBTreeFolder2Base.__init__(self, self.id) HBTreeFolder2Base.__init__(self, self.id)
return CMFHBTreeFolder._setObject(self, *args, **kw) return CMFHBTreeFolder._setObject(self, *args, **kw)
...@@ -977,7 +1026,9 @@ class Folder(CopyContainer, CMFBTreeFolder, CMFHBTreeFolder, Base, FolderMixIn): ...@@ -977,7 +1026,9 @@ class Folder(CopyContainer, CMFBTreeFolder, CMFHBTreeFolder, Base, FolderMixIn):
""" """
Return the named object from the folder. Return the named object from the folder.
""" """
if self._folder_handler == HBTREE_HANDLER: if self._folder_handler == PERSISTENT_MAPPING_HANDLER:
return ERP5PersistentMappingFolder.get(self, id, default)
elif self._folder_handler == HBTREE_HANDLER:
return CMFHBTreeFolder.get(self, id, default) return CMFHBTreeFolder.get(self, id, default)
else: else:
return CMFBTreeFolder.get(self, id, default) return CMFBTreeFolder.get(self, id, default)
...@@ -989,13 +1040,18 @@ class Folder(CopyContainer, CMFBTreeFolder, CMFHBTreeFolder, Base, FolderMixIn): ...@@ -989,13 +1040,18 @@ class Folder(CopyContainer, CMFBTreeFolder, CMFHBTreeFolder, Base, FolderMixIn):
The IDs are sequential to optimize access to objects The IDs are sequential to optimize access to objects
that are likely to have some relation. that are likely to have some relation.
""" """
if self._folder_handler == HBTREE_HANDLER: if self._folder_handler == PERSISTENT_MAPPING_HANDLER:
raise NotImplementedError
elif self._folder_handler == HBTREE_HANDLER:
return CMFHBTreeFolder.generateId(self, prefix, suffix, rand_ceiling) return CMFHBTreeFolder.generateId(self, prefix, suffix, rand_ceiling)
else: else:
return CMFBTreeFolder.generateId(self, prefix, suffix, rand_ceiling) return CMFBTreeFolder.generateId(self, prefix, suffix, rand_ceiling)
def __getattr__(self, name): def __getattr__(self, name):
if self._folder_handler == HBTREE_HANDLER: if self._folder_handler == PERSISTENT_MAPPING_HANDLER:
return ERP5PersistentMappingFolder.__getattr__(self, name)
#return ERP5PersistentMappingFolder.__getattr__(self, name)
elif self._folder_handler == HBTREE_HANDLER:
return CMFHBTreeFolder.__getattr__(self, name) return CMFHBTreeFolder.__getattr__(self, name)
else: else:
if self._tree is None: if self._tree is None:
...@@ -1003,7 +1059,9 @@ class Folder(CopyContainer, CMFBTreeFolder, CMFHBTreeFolder, Base, FolderMixIn): ...@@ -1003,7 +1059,9 @@ class Folder(CopyContainer, CMFBTreeFolder, CMFHBTreeFolder, Base, FolderMixIn):
return CMFBTreeFolder.__getattr__(self, name) return CMFBTreeFolder.__getattr__(self, name)
def __len__(self): def __len__(self):
if self._folder_handler == HBTREE_HANDLER: if self._folder_handler == PERSISTENT_MAPPING_HANDLER:
return ERP5PersistentMappingFolder.__len__(self)
elif self._folder_handler == HBTREE_HANDLER:
if self._htree is None: if self._htree is None:
return 0 return 0
return CMFHBTreeFolder.__len__(self) return CMFHBTreeFolder.__len__(self)
...@@ -1013,7 +1071,9 @@ class Folder(CopyContainer, CMFBTreeFolder, CMFHBTreeFolder, Base, FolderMixIn): ...@@ -1013,7 +1071,9 @@ class Folder(CopyContainer, CMFBTreeFolder, CMFHBTreeFolder, Base, FolderMixIn):
return CMFBTreeFolder.__len__(self) return CMFBTreeFolder.__len__(self)
def keys(self, *args, **kw): def keys(self, *args, **kw):
if self._folder_handler == HBTREE_HANDLER: if self._folder_handler == PERSISTENT_MAPPING_HANDLER:
return ERP5PersistentMappingFolder.keys(self, *args, **kw)
elif self._folder_handler == HBTREE_HANDLER:
if self._htree is None: if self._htree is None:
return [] return []
return CMFHBTreeFolder.keys(self, *args, **kw) return CMFHBTreeFolder.keys(self, *args, **kw)
...@@ -1023,7 +1083,9 @@ class Folder(CopyContainer, CMFBTreeFolder, CMFHBTreeFolder, Base, FolderMixIn): ...@@ -1023,7 +1083,9 @@ class Folder(CopyContainer, CMFBTreeFolder, CMFHBTreeFolder, Base, FolderMixIn):
return CMFBTreeFolder.keys(self, *args, **kw) return CMFBTreeFolder.keys(self, *args, **kw)
def values(self, *args, **kw): def values(self, *args, **kw):
if self._folder_handler == HBTREE_HANDLER: if self._folder_handler == PERSISTENT_MAPPING_HANDLER:
return ERP5PersistentMappingFolder.values(self, *args, **kw)
elif self._folder_handler == HBTREE_HANDLER:
if self._htree is None: if self._htree is None:
return [] return []
return CMFHBTreeFolder.values(self, *args, **kw) return CMFHBTreeFolder.values(self, *args, **kw)
...@@ -1033,7 +1095,9 @@ class Folder(CopyContainer, CMFBTreeFolder, CMFHBTreeFolder, Base, FolderMixIn): ...@@ -1033,7 +1095,9 @@ class Folder(CopyContainer, CMFBTreeFolder, CMFHBTreeFolder, Base, FolderMixIn):
return CMFBTreeFolder.values(self, *args, **kw) return CMFBTreeFolder.values(self, *args, **kw)
def items(self, *args, **kw): def items(self, *args, **kw):
if self._folder_handler == HBTREE_HANDLER: if self._folder_handler == PERSISTENT_MAPPING_HANDLER:
return ERP5PersistentMappingFolder.items(self, *args, **kw)
elif self._folder_handler == HBTREE_HANDLER:
if self._htree is None: if self._htree is None:
return [] return []
return CMFHBTreeFolder.items(self, *args, **kw) return CMFHBTreeFolder.items(self, *args, **kw)
...@@ -1043,7 +1107,9 @@ class Folder(CopyContainer, CMFBTreeFolder, CMFHBTreeFolder, Base, FolderMixIn): ...@@ -1043,7 +1107,9 @@ class Folder(CopyContainer, CMFBTreeFolder, CMFHBTreeFolder, Base, FolderMixIn):
return CMFBTreeFolder.items(self, *args, **kw) return CMFBTreeFolder.items(self, *args, **kw)
def iteritems(self, *args, **kw): def iteritems(self, *args, **kw):
if self._folder_handler == HBTREE_HANDLER: if self._folder_handler == PERSISTENT_MAPPING_HANDLER:
return self._object_dict.iteritem(*args, **kw)
elif self._folder_handler == HBTREE_HANDLER:
result = CMFHBTreeFolder._htree_iteritems(self, *args, **kw) result = CMFHBTreeFolder._htree_iteritems(self, *args, **kw)
else: else:
if self._tree is None: if self._tree is None:
...@@ -1052,7 +1118,9 @@ class Folder(CopyContainer, CMFBTreeFolder, CMFHBTreeFolder, Base, FolderMixIn): ...@@ -1052,7 +1118,9 @@ class Folder(CopyContainer, CMFBTreeFolder, CMFHBTreeFolder, Base, FolderMixIn):
return NullIter(((x, y.__of__(self)) for x, y in result)) return NullIter(((x, y.__of__(self)) for x, y in result))
def hasObject(self, id): def hasObject(self, id):
if self._folder_handler == HBTREE_HANDLER: if self._folder_handler == PERSISTENT_MAPPING_HANDLER:
return ERP5PersistentMappingFolder.hasObject(self, id)
elif self._folder_handler == HBTREE_HANDLER:
if self._htree is None: if self._htree is None:
return False return False
return CMFHBTreeFolder.hasObject(self, id) return CMFHBTreeFolder.hasObject(self, id)
...@@ -1520,7 +1588,12 @@ class Folder(CopyContainer, CMFBTreeFolder, CMFHBTreeFolder, Base, FolderMixIn): ...@@ -1520,7 +1588,12 @@ class Folder(CopyContainer, CMFBTreeFolder, CMFHBTreeFolder, Base, FolderMixIn):
# (no docstring to prevent publishing) # (no docstring to prevent publishing)
if meta_type is not None: if meta_type is not None:
spec = meta_type spec = meta_type
if self._folder_handler == BTREE_HANDLER: if self._folder_handler == PERSISTENT_MAPPING_HANDLER:
return ERP5PersistentMappingFolder.objectValues(
self, spec=spec, portal_type=portal_type, sort_on=sort_on,
sort_order=sort_order, checked_permission=checked_permission
)
elif self._folder_handler == BTREE_HANDLER:
if self._tree is None: if self._tree is None:
return [] return []
object_list = CMFBTreeFolder.objectValues(self, spec=spec) object_list = CMFBTreeFolder.objectValues(self, spec=spec)
......
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