from Products.CMFCore import MemberDataTool from Products.CMFCore.MemberDataTool import MemberDataTool as BaseTool from Products.CMFCore.MemberDataTool import MemberData as BaseData from Products.CMFPlone import ToolNames from Globals import InitializeClass from ZPublisher.Converters import type_converters from zExceptions import BadRequest from AccessControl import ClassSecurityInfo from Acquisition import aq_base from Products.BTreeFolder2.BTreeFolder2 import BTreeFolder2 from Products.CMFCore.utils import getToolByName from Products.CMFPlone.utils import log_deprecated from Products.CMFPlone.PloneBaseTool import PloneBaseTool from Products.CMFCore.permissions import SetOwnProperties, ManagePortal from ZODB.POSException import ConflictError class MemberDataTool(PloneBaseTool, BaseTool): meta_type = ToolNames.MemberDataTool security = ClassSecurityInfo() toolicon = 'skins/plone_images/user.gif' __implements__ = (PloneBaseTool.__implements__, BaseTool.__implements__, ) def __init__(self): BaseTool.__init__(self) self.portraits=BTreeFolder2(id='portraits') def _getPortrait(self, member_id): "return member_id's portrait if you can " return self.portraits.get(member_id, None) def _setPortrait(self, portrait, member_id): " store portrait which must be a raw image in _portrais " if self.portraits.has_key(member_id): self.portraits._delObject(member_id) self.portraits._setObject(id= member_id, object=portrait) def _deletePortrait(self, member_id): " remove member_id's portrait " if self.portraits.has_key(member_id): self.portraits._delObject(member_id) security.declarePrivate('pruneMemberDataContents') def pruneMemberDataContents(self): ''' Compare the user IDs stored in the member data tool with the list in the actual underlying acl_users and delete anything not in acl_users ''' BaseTool.pruneMemberDataContents(self) membertool= getToolByName(self, 'portal_membership') portraits = self.portraits user_list = membertool.listMemberIds() for tuple in portraits.items(): member_id = tuple[0] member_obj = tuple[1] if member_id not in user_list: self.portraits._delObject(member_id) security.declareProtected(ManagePortal, 'purgeMemberDataContents') def purgeMemberDataContents(self): ''' Delete ALL MemberData information. This is required for us as we change the MemberData class. ''' membertool= getToolByName(self, 'portal_membership') members = self._members for tuple in members.items(): member_name = tuple[0] member_obj = tuple[1] del members[member_name] return "Done." security.declarePrivate("updateMemberDataContents") def updateMemberDataContents(self,): """Update former MemberData objects to new MemberData objects """ count = 0 membertool= getToolByName(self, 'portal_membership') members = self._members properties = self.propertyIds() # Scan members for old MemberData for member_name, member_obj in members.items(): values = {} if getattr(member_obj, "_is_new_kind", None): continue # Do not have to upgrade that object # Have to upgrade. Create the values mapping. for pty_name in properties: user_value = getattr( member_obj, pty_name, _marker ) if user_value <> _marker: values[pty_name] = user_value # Wrap a new user object of the RIGHT class u = self.acl_users.getUserById(member_name, None) if not u: continue # User is not in main acl_users anymore self.wrapUser(u) # Set its properties mbr = self._members.get(member_name, None) if not mbr: raise RuntimeError, "Error while upgrading user '%s'." % (member_name, ) mbr.setProperties(values, force_local = 1) count += 1 return count security.declarePrivate( 'searchMemberDataContents' ) def searchMemberDataContents( self, search_param, search_term ): """ Search members. This is the same as CMFCore except that it doesn't check term case. """ res = [] search_term = search_term.strip().lower() if search_param == 'username': search_param = 'id' mtool = getToolByName(self, 'portal_membership') for member_id in self._members.keys(): user_wrapper = mtool.getMemberById( member_id ) if user_wrapper is not None: memberProperty = user_wrapper.getProperty searched = memberProperty( search_param, None ) if searched is not None: if searched.strip().lower().find(search_term) != -1: res.append( { 'username': memberProperty( 'id' ) , 'email' : memberProperty( 'email', '' ) } ) return res security.declarePublic( 'searchFulltextForMembers' ) def searchFulltextForMembers(self, s): """search for members which do have string 's' in name, email or full name (if defined) this is mainly used for the localrole form """ s=s.strip().lower() portal = self.portal_url.getPortalObject() mu = self.portal_membership is_manager = mu.checkPermission('Manage portal', self) res = [] for member in mu.listMembers(): u = member.getUser() if not (member.listed or is_manager): continue if u.getUserName().lower().find(s) != -1 \ or member.getProperty('fullname').lower().find(s) != -1 \ or member.getProperty('email').lower().find(s) != -1: res.append(member) return res MemberDataTool.__doc__ = BaseTool.__doc__ InitializeClass(MemberDataTool) _marker = [] # Create a new marker object. class MemberData(BaseData): meta_type='Plone MemberData' security = ClassSecurityInfo() _is_new_kind = 1 def __init__(self, *args, **kw): log_deprecated("The CMFPlone.MemberData class will be removed in Plone 3.0") BaseData.__init__(self, *args, **kw) security.declareProtected(SetOwnProperties, 'setProperties') def setProperties(self, properties=None, **kw): '''Allows the authenticated member to set his/her own properties. Accepts either keyword arguments or a mapping for the "properties" argument. ''' log_deprecated("The CMFPlone.MemberData class will be removed in Plone 3.0") if properties is None: properties = kw membership = getToolByName(self, 'portal_membership') registration = getToolByName(self, 'portal_registration', None) if not membership.isAnonymousUser(): member = membership.getAuthenticatedMember() if registration: failMessage = registration.testPropertiesValidity(properties, member) if failMessage is not None: raise BadRequest, failMessage member.setMemberProperties(properties) else: raise BadRequest, 'Not logged in.' security.declarePublic('getProperty') def getProperty(self, id, default=_marker): log_deprecated("The CMFPlone.MemberData class will be removed in Plone 3.0") tool = self.getTool() base = aq_base( self ) # Check if we've got a marker asking us to get the value from the user object from_user = getattr(self, "%s_USER" % id, None) # First, check the wrapper (w/o acquisition). value = getattr( base, id, _marker ) # Then, check the tool and the user object for a value. tool_value = tool.getProperty( id, _marker ) user_value = getattr( self.getUser(), id, _marker ) # New Plone behaviour: use user value if we've set it if from_user: if user_value is not _marker: return user_value # Return stored value if we've got one if value is not _marker: return value # If the tool doesn't have the property, use user_value or default if tool_value is _marker: if user_value is not _marker: return user_value elif default is not _marker: return default else: raise ValueError, 'The property %s does not exist' % id # If the tool has an empty property and we have a user_value, use it if not tool_value and user_value is not _marker: return user_value # Otherwise return the tool value return tool_value security.declarePrivate('setMemberProperties') def setMemberProperties(self, mapping, force_local = 0): '''Sets the properties of the member. If force_local is true, values will not be stored in the underlying user folder ''' log_deprecated("The CMFPlone.MemberData class will be removed in Plone 3.0") # Sets the properties given in the MemberDataTool. tool = self.getTool() for id in tool.propertyIds(): if mapping.has_key(id): if not self.__class__.__dict__.has_key(id): value = mapping[id] if type(value)==type(''): proptype = tool.getPropertyType(id) or 'string' if type_converters.has_key(proptype): value = type_converters[proptype](value) # Try to update the property with GRUF's API try: if force_local: raise RuntimeError, "Force storing in the MemberData object" # If it works, add a marker to retreive the data from the user object self.setProperty(id, value) # This is GRUF's method setattr(self, "%s_USER" % id, 1) except ConflictError: raise except: # It didn't work... use the regular way, then - and remove the marker setattr(self, id, value) setattr(self, "%s_USER" % id, 0) # Remove the marker # Hopefully we can later make notifyModified() implicit. self.notifyModified() MemberData.__doc__ = BaseData.__doc__ InitializeClass(MemberData)