obct537
obct537

Reputation: 63

Extending the personal preferences page

I'm attempting to make an add-on that, among other things, adds another option to the personal preferences page. I've tried to piece together how to do this properly from various guides on loosely related topics, but I've had no luck. I'm just getting into Plone development, and a lot of this is somewhat foreign to me, so please be kind :)

I'm doing all this in Plone 4.3

When I have the add-on enabled on the site, it doesn't give me any errors, but the extra field isn't included on the preferences page.

So far, I've got something like this, ignore the odd naming scheme. Again, this was pieced together from other guides, and I wanted to get it working before I refactored.

userdataschema.py

from plone.app.users.browser.personalpreferences import IPersonalPreferences
from zope.interface import Interface
from zope import schema


class IEnhancedUserDataSchema(IPersonalPreferences):
    """ Use all the fields from the default user data schema, and add various
    extra fields.
    """

    buttonsEnabled = schema.Bool(title=u'Transition button widget.', 
                                default=True,
                                description=u'Uncheck to remove the transition button box from ALL pages.',
                                required=False
                                )  

adapter.py:

from plone.app.users.browser.personalpreferences import PersonalPreferencesPanelAdapter
from app.statebuttons.userdataschema import IEnhancedUserDataSchema
from zope.interface import implements

class EnhancedUserDataPanelAdapter(PersonalPreferencesPanelAdapter):
    """
    """
    implements(IEnhancedUserDataSchema)

    def get_buttonEnabled(self):
        return self.context.getProperty('buttonsEnabled', '')
    def set_buttonsEnabled(self, value):
        return self.context.setMemberProperties({'buttonsEnabled': value})
    buttonsEnabled = property(get_buttonEnabled, set_buttonsEnabled)

overrides.zcml:

<configure
    xmlns="http://namespaces.zope.org/zope"
    i18n_domain="collective.examples.userdata">

  <adapter 
    provides=".userdataschema.IEnhancedUserDataSchema"
    for="Products.CMFCore.interfaces.ISiteRoot"
    factory=".adapter.EnhancedUserDataPanelAdapter"
    />

</configure>

If anyone could give me some input on what I'm doing wrong, that would be awesome. If I'm way off the mark, I'd appreciate some input on where to go next.

Upvotes: 4

Views: 438

Answers (2)

fRiSi
fRiSi

Reputation: 1238

overwriting personal-preferences should not be necessary. just follow the documentation on https://pypi.python.org/pypi/plone.app.users

seems you're missing:

  • a userdatascheaprovider

    from plone.app.users.userdataschema import IUserDataSchemaProvider class UserDataSchemaProvider(object): implements(IUserDataSchemaProvider)

    def getSchema(self):
        """
        """
        return IEnhancedUserDataSchema
    
  • the GS configuration for it in componentregistry.xml:

  • a registration of your new field in GS properties.xml to make the field show up on the registration page (optionally)

    <object name="site_properties" meta_type="Plone Property Sheet">
    
        <property name="user_registration_fields" type="lines" purge="False">
            <element value="yourfield" />
        </property>
    
    </object>
    

to make your field show up in personal preferences follow the documentation on https://pypi.python.org/pypi/plone.app.users/1.1.5 section "How to update the personal information form"

Upvotes: 3

Dan Jacka
Dan Jacka

Reputation: 1782

You can make your new field show up on @@personal-preferences by adding this to your existing code:

browser/configure.zcml

<configure
    xmlns="http://namespaces.zope.org/zope"
    xmlns:browser="http://namespaces.zope.org/browser">

    <browser:page
      for="plone.app.layout.navigation.interfaces.INavigationRoot"
      name="personal-preferences"
      class=".personalpreferences.CustomPersonalPreferencesPanel"
      permission="cmf.SetOwnProperties"
      layer="..interfaces.IAppThemeLayer"
      />

</configure>

browser/personalpreferences.py

from plone.app.users.browser.personalpreferences import PersonalPreferencesPanel
from plone.app.users.browser.personalpreferences import LanguageWidget
from plone.app.users.browser.personalpreferences import WysiwygEditorWidget
from zope.formlib import form
from app.statebuttons.userdataschema import IEnhancedUserDataSchema

class CustomPersonalPreferencesPanel(PersonalPreferencesPanel):

    form_fields = form.FormFields(IEnhancedUserDataSchema)
    # Apply same widget overrides as in the base class
    form_fields['language'].custom_widget = LanguageWidget
    form_fields['wysiwyg_editor'].custom_widget = WysiwygEditorWidget

Note that you'll need a browser layer IAppThemeLayer registered in profiles/default/browserlayer.xml, and to define storage for your field in profiles/default/memberdata_properties.xml.

You can see why this is necessary in plone.app.users.browser.personalpreferences. IPersonalPreferences is looked up as follows:

class PersonalPreferencesPanel(AccountPanelForm):

    ...
    form_fields = form.FormFields(IPersonalPreferences)
    ...

The schema is bound to the IPersonalPreferences interface. You have to change the control panel in order to change the looked-up schema.

Instead you could use the IUserDataSchema approach described in https://pypi.python.org/pypi/collective.examples.userdata but as you've seen in order to override @@personal-information you need to use overrides.zcml which is an if-all-else-fails kind of override and not a very welcome citizen in a third party add-on.

Others may disagree but my personal preference (should I say my IPersonalPreference?) for this kind of problem is to create a dedicated form for the setting(s) and link to it from e.g. the personal tools menu.

Upvotes: 3

Related Questions