This will be a Drupal 6 and only Drupal 6 module due to the changes in Drupal 7.

I wondering about the base interest in this idea and what base line features are of most interest to users.

I have implemented a simple field like api and the following fields.

Output is controlled by a theme callback (the formattor), and input widget is created via widget.

The demo is at http://www.caignwebs.com.au/contributions/profile_extras.zip

<?php
/**
 * The new Profile fields added by this module.
 *
 * Administrative features.
 *
 * Additional data storage is done via the {profile}.options
 * field. To use this, specify the form & file that is required
 * to render this element using the parameters 'options form'
 * and 'options form file'. If the flag '#serialize' is set on
 * the element the form value is serialized before being written
 * to the database. It is up to the each element to handle
 * unserializing this data.
 *
 * TODO - Implement
 * The autocomplete option must be the full autocomplete path.
 *
 * View operations
 *
 * The default behaviour is to simply show the value, but you can
 * define a formatter for the new element type. This should be
 * the name of a standard Drupal theme function.
 *
 * The parameters are the raw user data and the field details.
 *
 * @return array()
 */
function profile_extras_profile_fields() {
  return array(
    'keyed_selection' => array(
      'title' => t('Keyed selection'),
      'description' => t('Standard select list with each option having a key. This allows users to change the options text without losing existing relationships for existing users.'),
      'multiple' => 1,
      'module' => 'profile_extras',
      'options form' => 'profile_extra_keyed_selection_options',
      'options form file' => 'profile_extras.admin.inc',
      'formatter' => 'profile_field_keyed_selection',
      'widget' => 'profile_field_keyed_selection_widget',
    ),
    'keyed_selection_multi' => array(
      'title' => t('Keyed selection - multiple select'),
      'description' => t('Standard select list with each option having a key. This allows users to change the options text without losing existing relationships for existing users.'),
      'multiple' => 0,
      'module' => 'profile_extras',
      'options form' => 'profile_extra_keyed_selection_options',
      'options form file' => 'profile_extras.admin.inc',
      'formatter' => 'profile_field_keyed_selection',
      'widget' => 'profile_field_keyed_selection_widget',
    ),
    'user_reference' => array(
      'title' => t('User reference'),
      'description' => t('User reference'),
      'multiple' => 1,
      'module' => 'profile_extras',
      'options form' => 'profile_extra_user_reference_options',
      'options form file' => 'profile_extras.admin.inc',
      'formatter' => 'profile_field_user_reference',
      'widget' => 'profile_field_user_reference_widget',
    ),
    'user_reference_multi' => array(
      'title' => t('User references'),
      'description' => t('User reference - multiple select'),
      'multiple' => 0,
      'module' => 'profile_extras',
      'options form' => 'profile_extra_user_reference_options',
      'options form file' => 'profile_extras.admin.inc',
      'formatter' => 'profile_field_user_reference',
      'widget' => 'profile_field_user_reference_widget',
    ),
    'node_reference' => array(
      'title' => t('Node reference'),
      'description' => t('Node reference'),
      'multiple' => 1,
      'module' => 'profile_extras',
      'options form' => 'profile_extra_node_reference_options',
      'options form file' => 'profile_extras.admin.inc',
      'formatter' => 'profile_field_node_reference',
      'widget' => 'profile_field_node_reference_widget',
    ),
    'node_reference_multi' => array(
      'title' => t('Node references'),
      'description' => t('Node reference - multiple select'),
      'multiple' => 0,
      'module' => 'profile_extras',
      'options form' => 'profile_extra_node_reference_options',
      'options form file' => 'profile_extras.admin.inc',
      'formatter' => 'profile_field_node_reference',
      'widget' => 'profile_field_node_reference_widget',
    ),
  );
}
?>

More latter

Comments

alan d.’s picture

Just noticed that I still have a Devel function call to DPM() in the above zip - delete the form_alter that has this function call before using it. This extra code has now been removed.

This has had limited testing and introducing to the community for quick comments before locking in the base API as the current project where we need this functionality is finished ( < 2 weeks ).

Note that Content Profile gives you similar functionality via CCK fields indirectly using a 1-1 node to user relationship.

Features

For those that don't like reading code, it supplies the following fields.

# Keyed selection
# Keyed selection - multiple select
# User reference
# User references
# Node reference
# Node references

The "Keyed selection" allows the use of a keyed list. That is, a list that can have it's items renamed without losing data.

The user reference is a simple select list. This has a role based filter. Will consider an autocomplete

The node reference is also a simple select list. Each profile field has a node type filter on it.

Singles / Multiple types are completely separate to keep things as simple as possible. There is no switching between them, but they share the same base theming call.

Other features
I added a code based hook that has primary control on if the Category tabs are visible. This defaults to the standard control if no module restricts the access.

Plans
The project that I'm writing will need checkboxes, so a simple widget selector will be built in for the multiples. Select lists, checkboxes, and autocompletes are planned.

If profile roles does not work with this module, then restrictions based on role per profile field will also be built in.

Code summary

The base system attempts to build on the core Profile using a variety of different techniques.

The above hook is called to generate the available profile fields that are combined with the core's fields. This means that user objects that are not built via user_load, may not be initialised correctly by those modules that use a direct query + profile_load_profile($account); will not have these extra fields. These would require a - the use of user_load or b - adding profile_extras_load_profile($account);

A form alter is used to append these new fields to the "admin/user/profile" page

A menu alter is used to change the form arguments to the edit / add profile fields, and sadly the entire function is copied from core for about 4 lines of changed code. This could be an issue with existing modules that use the form id to hook into this form.

Most other functionality is via addtions done using hook_user

The multiple flag is vital in how the system handles the data: Single values are handled via Profile as a simple string field, but multiple (0 - unlimited, x - # restriction but this is not implemented) means that the new API will save this in a new table, {profile_extra_values}, fid / uid / delta / value

All feedback - good & bad - will be welcome.


Alan Davison