############################################################################## # # Copyright (c) 2005 Nexedi SARL and Contributors. All Rights Reserved. # Jerome Perrin <jerome@nexedi.com> # # WARNING: This program as such is intended to be used by professional # programmers who take the whole responsability of assessing all potential # consequences resulting from its eventual inadequacies and bugs # End users who are looking for a ready-to-use solution with commercial # garantees and support are strongly adviced to contract a Free Software # Service Company # # This program is Free Software; you can redistribute it and/or # modify it under the terms of the GNU General Public License # as published by the Free Software Foundation; either version 2 # of the License, or (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. # ############################################################################## from AccessControl import ClassSecurityInfo, getSecurityManager from Globals import InitializeClass, DTMLFile from Acquisition import aq_base from zLOG import LOG, INFO from Products.CMFCore.utils import getToolByName from Products.ERP5Type.Tool.BaseTool import BaseTool from Products.ERP5Type import Permissions from Products.ERP5Type.Cache import CachingMethod from Products.ERP5Type.Utils import convertToUpperCase from Products.ERP5Type.Accessor.TypeDefinition import list_types from Products.ERP5Form.Document.Preference import Preference from Products.ERP5Form import _dtmldir class PreferenceTool(BaseTool): """ PreferenceTool manages User Preferences / User profiles. """ id = 'portal_preferences' meta_type = 'ERP5 Preference Tool' portal_type = 'Preference Tool' title = 'Preferences' allowed_types = ( 'ERP5 Preference',) security = ClassSecurityInfo() security.declareProtected( Permissions.ManagePortal, 'manage_overview' ) manage_overview = DTMLFile( 'explainPreferenceTool', _dtmldir ) security.declareProtected( Permissions.ManagePortal, 'manage_group_preferences' ) manage_group_preferences = DTMLFile( 'PreferenceTool_managePreferences', _dtmldir ) manage_options = ( BaseTool.manage_options + ( { 'label' : 'User Groups Preferences' , 'action' : 'manage_group_preferences'},)) security.declarePrivate('manage_afterAdd') def manage_afterAdd(self, item, container) : """ init the permissions right after creation """ item.manage_permission(Permissions.AddPortalContent, ['Member', 'Author', 'Manager']) item.manage_permission(Permissions.View, ['Member', 'Auditor', 'Manager']) BaseTool.inheritedAttribute('manage_afterAdd')(self, item, container) def _aq_dynamic(self, name): """ if the name is a valid preference, then start a lookup on active preferences. """ dynamic = BaseTool._aq_dynamic(self, name) if dynamic is not None : return dynamic aq_base_name = getattr(aq_base(self), name, None) if aq_base_name is not None : return aq_base_name if name in self.getValidPreferencePropertyIdList() : return self.getPreference(name) security.declareProtected(Permissions.View, "getPreference") def getPreference(self, pref_name) : """ get the preference on the most appopriate Preference object. """ def _getPreference(pref_name="", user_name="") : found = 0 MARKER = [] for pref in self._getSortedPreferenceList() : attr = getattr(pref, pref_name, MARKER) if attr is not MARKER : found = 1 # test the attr is set if callable(attr) : value = attr() else : value = attr if value not in (None, '', (), []) : return attr if found : return attr _getPreference = CachingMethod( _getPreference, id='PreferenceTool.CachingMethod') user_name = getSecurityManager().getUser().getId() return _getPreference(pref_name=pref_name, user_name=user_name) security.declareProtected(Permissions.ModifyPortalContent, "setPreference") def setPreference(self, pref_name, value) : """ set the preference on the active Preference object""" self.getActivePreference()._edit(**{pref_name:value}) security.declareProtected(Permissions.View, "getValidPreferencePropertyIdList") def getValidPreferencePropertyIdList(self) : """ return the list of attributes that are preferences names and should be looked up on Preferences. """ def _getValidPreferencePropertyIdList(self) : """ a cache for this method """ attr_list = [] try : pref_portal_type = getToolByName(self, 'portal_types')['Preference'] except KeyError : # When creating an ERP5 Site, this method is called, but the # type is not installed yet return [] # 'Dynamic' property sheets added through ZMI zmi_property_sheet_list = [] for property_sheet in pref_portal_type.property_sheet_list : try: zmi_property_sheet_list.append( getattr(__import__(property_sheet), property_sheet)) except ImportError, e : LOG('PreferenceTool._getValidPreferencePropertyIdList', INFO, 'unable to import Property Sheet %s' % property_sheet, e) # 'Static' property sheets defined on the class class_property_sheet_list = Preference.property_sheets for property_sheet in ( tuple(zmi_property_sheet_list) + class_property_sheet_list ) : # then generate common method names for prop in property_sheet._properties : if not prop.get('preference', 0) : # only properties marked as preference are used continue attribute = prop['id'] attr_list += [ attribute, 'get%s' % convertToUpperCase(attribute), 'get%sId' % convertToUpperCase(attribute), 'get%sTitle' % convertToUpperCase(attribute), ] if prop['type'] in list_types : attr_list += ['get%sList' % convertToUpperCase(attribute), ] for attribute in list(getattr(property_sheet, '_categories', [])) : attr_list += [ attribute, 'get%s' % convertToUpperCase(attribute), 'get%sId' % convertToUpperCase(attribute), 'get%sTitle' % convertToUpperCase(attribute), 'get%sValue' % convertToUpperCase(attribute), 'get%sValueList' % convertToUpperCase(attribute), 'get%sItemList' % convertToUpperCase(attribute), 'get%sIdList' % convertToUpperCase(attribute), 'get%sTitleList' % convertToUpperCase(attribute), 'get%sList' % convertToUpperCase(attribute), ] return attr_list _getValidPreferencePropertyIdList = CachingMethod( _getValidPreferencePropertyIdList, cache_duration = 600, id = 'PreferenceTool._getPreferenceAttributes') return _getValidPreferencePropertyIdList(self) security.declarePrivate('_getSortedPreferenceList') def _getSortedPreferenceList(self) : """ return the most appropriate preferences objects, sorted so that the first in the list should be applied first """ prefs = [] # XXX This will not work with 1000000 users (searchFolder required) # XXX will also cause problems with Manager (too long) # XXX Use catalog instead of contentValues (ex. searchFolder) # XXX For manager, create a manager specific preference # or better solution for pref in self.contentValues(spec=('ERP5 Preference', )) : pref = pref.getObject() if pref.getPreferenceState() == 'enabled' : prefs.append(pref) prefs.sort(lambda b, a: cmp(a.getPriority(), b.getPriority())) return prefs security.declareProtected(Permissions.View, 'getActivePreference') def getActivePreference(self) : """ returns the current preference for the user. Note that this preference may be read only. """ enabled_prefs = self._getSortedPreferenceList() if len(enabled_prefs) > 0 : return enabled_prefs[0] security.declareProtected(Permissions.View, 'getDocumentTemplate') def getDocumentTemplate(self, folder) : """ returns all document templates that are in acceptable Preferences based on different criteria such as folder, portal_type, etc. XXX This spec still needs to be refined before implementation """ acceptable_templates = [] for pref in self._getSortedPreferenceList() : for doc in pref.objectValues() : if hasattr(doc, 'getTemplateDestinationUidList') and \ folder.getUid() in doc.getTemplateDestinationUidList() : acceptable_templates.append (doc) return acceptable_templates security.declareProtected(Permissions.ManagePortal, 'USELESS_manage_updateUserGroupsPreferences') def USELESS_manage_updateUserGroupsPreferences(self, REQUEST) : """ action edit Users Groups Preferences from the management sceen XXX This is not compatible with 1,000,000 preferences Also, the type of preference (or, better, the priority) must be *stored* on the preference itself and set from the preference itself. This API is therefore useless. """ for k, v in REQUEST.items() : if k.startswith("preference_priority_") : self[k[len('preference_priority_'):]].setPriority(v) if REQUEST is not None: return self.manage_group_preferences( self, REQUEST, manage_tabs_message='Preference Priorities Updated') InitializeClass(PreferenceTool)