PreferenceTool.py 10.1 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
##############################################################################
#
# 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.
#
##############################################################################

29
from AccessControl import ClassSecurityInfo, getSecurityManager
30 31
from Globals import InitializeClass, DTMLFile
from Acquisition import aq_base
32
from zLOG import LOG, INFO
33 34 35 36 37 38

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
39
from Products.ERP5Type.Accessor.TypeDefinition import list_types
40
from Products.ERP5Form.Document.Preference import Preference
41 42 43 44 45 46 47
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'
Jérome Perrin's avatar
Jérome Perrin committed
48
  title         = 'Preferences'
49 50 51 52 53 54
  allowed_types = ( 'ERP5 Preference',)
  security      = ClassSecurityInfo()

  security.declareProtected(
       Permissions.ManagePortal, 'manage_overview' )
  manage_overview = DTMLFile( 'explainPreferenceTool', _dtmldir )
55

56 57 58 59
  security.declareProtected(
       Permissions.ManagePortal, 'manage_group_preferences' )
  manage_group_preferences = DTMLFile(
       'PreferenceTool_managePreferences', _dtmldir )
60

61 62 63
  manage_options = ( BaseTool.manage_options +
                     ( { 'label'      : 'User Groups Preferences'
                       , 'action'     : 'manage_group_preferences'},))
64

65 66 67 68 69 70 71 72
  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)
73

74 75 76 77 78 79 80 81 82
  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
83
    if name in self.getValidPreferencePropertyIdList() :
84
      return self.getPreference(name)
85

86 87 88
  security.declareProtected(Permissions.View, "getPreference")
  def getPreference(self, pref_name) :
    """ get the preference on the most appopriate Preference object. """
89
    def _getPreference(pref_name="", user_name="") :
90 91
      found = 0
      MARKER = []
92
      for pref in self._getSortedPreferenceList() :
93 94 95 96 97 98 99 100 101 102 103 104 105 106 107
        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()
108
    return _getPreference(pref_name=pref_name, user_name=user_name)
109

110 111 112 113
  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})
114 115 116

  security.declareProtected(Permissions.View, "getValidPreferencePropertyIdList")
  def getValidPreferencePropertyIdList(self) :
117 118
    """ return the list of attributes that are preferences names and
       should be looked up on Preferences. """
119
    def _getValidPreferencePropertyIdList(self) :
120 121 122 123 124 125 126 127
      """ 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 []
128
      # 'Dynamic' property sheets added through ZMI
129 130 131 132 133 134
      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 :
135
          LOG('PreferenceTool._getValidPreferencePropertyIdList', INFO,
136
               'unable to import Property Sheet %s' % property_sheet, e)
137 138
      # 'Static' property sheets defined on the class
      class_property_sheet_list = Preference.property_sheets
139
      for property_sheet in ( tuple(zmi_property_sheet_list) +
140
                              class_property_sheet_list ) :
141
        # then generate common method names 
142
        for prop in property_sheet._properties :
143 144 145
          if not prop.get('preference', 0) :
            # only properties marked as preference are used
            continue
146 147 148 149 150 151 152 153
          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', [])) :
154 155 156 157
          attr_list += [ attribute,
                         'get%s' % convertToUpperCase(attribute),
                         'get%sId' % convertToUpperCase(attribute),
                         'get%sTitle' % convertToUpperCase(attribute),
158

159 160 161 162 163 164
                         'get%sValue' % convertToUpperCase(attribute),
                         'get%sValueList' % convertToUpperCase(attribute),
                         'get%sItemList' % convertToUpperCase(attribute),
                         'get%sIdList' % convertToUpperCase(attribute),
                         'get%sTitleList' % convertToUpperCase(attribute),
                         'get%sList' % convertToUpperCase(attribute), ]
165
      return attr_list
166 167
    _getValidPreferencePropertyIdList = CachingMethod(
                      _getValidPreferencePropertyIdList, cache_duration = 600,
168
                      id = 'PreferenceTool._getPreferenceAttributes')
169
    return _getValidPreferencePropertyIdList(self)
170

171 172
  security.declarePrivate('_getSortedPreferenceList')
  def _getSortedPreferenceList(self) :
173
    """ return the most appropriate preferences objects,
174 175
        sorted so that the first in the list should be applied first
    """
176
    prefs = []
177 178 179 180 181
    # 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
182
    for pref in self.contentValues(spec=('ERP5 Preference', )) :
183
      pref = pref.getObject()
184
      if pref.getPreferenceState() == 'enabled' :
185 186 187
        prefs.append(pref)
    prefs.sort(lambda b, a: cmp(a.getPriority(), b.getPriority()))
    return prefs
188
    
189 190 191 192
  security.declareProtected(Permissions.View, 'getActivePreference')
  def getActivePreference(self) :
    """ returns the current preference for the user. 
       Note that this preference may be read only. """
193
    enabled_prefs = self._getSortedPreferenceList()
194 195 196
    if len(enabled_prefs) > 0 :
      return enabled_prefs[0]

197 198
  security.declareProtected(Permissions.View, 'getDocumentTemplate')
  def getDocumentTemplate(self, folder) :
199
    """ returns all document templates that are in acceptable Preferences 
200 201 202 203
        based on different criteria such as folder, portal_type, etc.

        XXX This spec still needs to be refined before implementation
    """
204
    acceptable_templates = []
205
    for pref in self._getSortedPreferenceList() :
206 207 208 209 210 211 212
      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,
213 214 215 216 217 218 219 220 221 222 223 224 225
          '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.
    """
226 227 228 229 230 231 232 233 234
    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)