Note:

If you want to create a new page for developers, you should create it on the Moodle Developer Resource site.

User preferences for plug-ins

From MoodleDocs

NOTE: This page is about a potential feature that never landed, it appears completely out of date.

This page is associated with discussion about allowing plug-ins to declare their own user settings screens.

Overview

One strand of development for the Open University UK's next generation VLE focusses on features which allow the student to be able to personalise their experience with various different parts of the system. What it boils down to is them being able to switch bits on and off.

What I'd like is for a plug-in (module, block, course format, local plug-in...) to be able to define a user settings screen that relates to the plug-in. Each plug-in would offer its own settings screen, and would place links to that screen at suitable place(s) in their own user interface. Additionally, a link to the settings screen would be automatically added to the profile section of the settings block, wherever it appears. This would gather together user preferences in a single location, making them easy to find.

When the user views the settings screen, their current settings will be displayed. An Edit button will allow them to make changes.

Discarded thoughts

Initially I thought this could be done through the custom user profile fields, where each plug-in would define a custom profile category (only editable through code) and each category would be displayed as a separate item in the profile settings navigation.

There was a lot of concern (see MDL-26347 comments) from Eloy and Petr about interdependence of functionality.

This new proposal builds on a suggestion from Tim in the forum thread to use user_preferences instead, since this does not have a UI for admins to interact with. Tim, Sam and I have worked together to rough this outline for further discussion...

User interface mock-ups

1. a custom plug-in's main screen - showing its link to its settings screen

userprefs pluginscreen.jpg

2. a custom plug-in's setting screen in read mode - also showing the settings block with links to other settings

Userprefs readscreen.png

3. a custom plug-in's setting screen in edit mode

Userprefs edit.png

4. forum settings

Userpref forum.png

Database

Structure

User preferences will be stored in the existing core user_preferences table, rather than in tables associated with the plug-in.

The user_preferences table will be extended to add a plug-in column, for improved data integrity (optional - the rest of this design could work without this change, either in the short term to allow an early inclusion in 2.0.x or for ever).

Current best practice is to include the plug-in name in the name of the user_preference, so this extension will simplify that. The table will be populated as follows

  • Userid
    • the id number for current $USER
    • as currently defined
  • plugin (or maybe component if that's newer moodle style)
    • frankenstyle name
    • allowed null for backward compatibility
  • Name
    • the setting being stored
    • as currently defined
  • value
    • the user's choice
    • as currently defined

Get and Set functions

The data continues to be accessed through the existing functions which are extended to cope with the optional plugin parameter.

get_user_preferences

An additional optional plugin parameter will be added. This will default to null if no parameter is passed, for backward compatibility.

If the plugin parameter is received then this, as well as the name and user parameters will be checked when accessing the data. Otherwise, just the name and user parameters, and a null plugin value will be checked.

set_user_preference

An additional optional plugin parameter will be added. This will default to null if no parameter is passed, for backward compatibility.

If the plugin parameter is received then this, as well as the name and user parameters will be inserted in the database. Otherwise, just the name and user parameters, and a null plugin value will be inserted.

set_user_preferences

This function takes an array of key/value pairs and saves all of them in the user_preferences table. This would be extended to optionally take an array of arrays of key/value pairs.

The first array would be indexed with the plugin name, so $array['plugin1'] contains all the key/value pairs for plugin1.

If an array of arrays is received, then each array's key/value pairs are inserted with the array's index inserted as the plugin value in the database row. If a simple array of key/value pairs is received, these are inserted with a null plugin value.

Update Tim points out that you'd be unlikely to want to set multiple plug-ins at the same time, which is very true. Its probably not something we should encourage either. So maybe it would be better to simply add another parameter (optional, default null as with set_user_preference()) with the plugin name.

Settings block

The Settings block currently includes a Profile section, which expands to offer a link to edit profile. Users with the right permissions also see change password, roles and security key links.

This profile section will be extended to add a link to each of the user preferences screens defined by plugins. The link will be highlighted with CSS to indicate the currently open page.

The links can be added in navigationlib.php by adding a loop through all enabled plugins (of all types) looking for an appropriately named file (see below) defining a user preferences form. If found, a function call would check whether the link should be added (see below), and if returns true a link to the form will be included in the profile navigation.

Userpref settingblock.gif

Block display

Initially I thought that the user/edit.php pages should display the Settings block. Given that the settings block and the "my profile" section is available all over the place, I'm not sure this is strictly necessary. When you're editing your profile, so you really need to jump to other places? You don't have the block there already with your "change password" link.

If we do want the settings block on the edit profile screen, it's pagelayout will need to be set to something that displays user blocks to match the profile page. The user/edit page already has user pagetype, but a course context. This will cause difficulties with the block display and overlaps with issues Sam has reported in MDL-25189. Some core themes (e.g. boxxie - it may be the only one, I haven't checked) add blocks on the user/edit.php page. These would need to be updated to remove that control, as being no longer necessary.

Plug-in interface

Defining the form

An optional file (userpreferences.php) will be added to each plugin which wants to define a user preferences interface.

Each userpreferences.php file will create a new form. This will not be a complete moodleform definition but a simpler definition similar to the way admin configuration settings.php files work. However, since the forms will be aimed at users rather than admins, the form fields will optionally need additional help text.

A new class of user_settingpage will be set up, so that the userpreferences.php file will start with:

   $settings = new user_settingpage('format_studyplan', get_string('pluginname','format_studyplan'));

Then each setting will be added like this:

   $settings->add(new user_setting_checkbox('format_studyplan_enablenotes', get_string('enablenotes_label', 'format_studyplan'), get_string('enablenotes_prompt', 'format_studyplan'), get_string('enablenotes_help', 'format_studyplan'), true, PARAM_INT));

To be completed - I'm not sure yet what the user_setting classes would need to do (how much can they inherit from admin_setting), and what we'd need to write so that when a user clicks on plugin/userpreferences.php link in the website they get the form rendered correctly.

Generated settings form

The save and cancel buttons should intuitively take you back to the course home page. If the user visits their profile from a course home or content page, the global $COURSE variable will be available and the id property can be used to define the redirect. Alternatively, the lastcourseaccess property of the global $USER variable stores the last visit on all their available courses, and so can be used to identify the last course they looked at for the definition of the redirect. If the lastcourseaccess property of the global $USER variable is empty, the user should be redirected to the latest course on which they were enrolled.

Example plug-in form:

userpref Studyplansettings.gif

Admin override

It is possible that system administrators may want to hide the user preferences for simplicity. The userpreferences.php file (or the plug-in class definition??) will include a function (plugin_userprefs_link maybe??) which indicates whether or not the settings block profile link should be included. This will return true by default for all plugins.

However, plug-in developers making use of this feature should include an admin settings screen with an on/off checkbox, and then their choice would be returned rather than the default true.

As an extension of this, plug-in developers might give administrators the option to switch on and off individual settings within the plug-in's user preferences form. If all individual settings were disabled, the plugin_userprefs_link function should check this situation and return false regardless of the general admin on/off setting.

Backup and restore

User settings, because they are stored using the core user_preferences functionality are already catered for in backup and restore procedures, so no further extension will be required.


Further tidying up possible

A number of fields on the current user profile form could be moved and placed more appropriately with their plug-ins, or into a new form for general preferences. This would leave the main profile form solely responsible for personal data about the user.

Here is a list of current user profile fields which fall into this situation - most would problably move to a "general" tab as they affect multiple plugins. In particular, I'm not sure what to do with the messaging ones, as they shouldn't be disabled if system private messaging is disabled, but they don't belong just with forum.

  • General
    • Use HTML editor (possibly some new ones coming related to this too)
    • Ajax and JavaScript
    • Screen reader
    • Preferred language
  • Messaging
    • Email format
    • Email display
    • Email digest type
  • Forum
    • Forum autosubscribe
    • Forum tracking