doc/developer/UserProfiles

Contributors: Benoit Grégoire, Last update: 2007-05-10 Feel free to contribute and/or format better

User profile design

The profiling is implemented as a list of allowable field defined by the network, that can be filled in by the user.

Initial design is from by Benoit Grégoire. Mostly implemented by François Proulx and Benoit Grégoire.

Why such a complicated framework, and not a few basic, commonly used fields?

Originally I was hoping to build a profile system with a core set of generic, semantically interoperable data elements (including links to services), that could be extended with network specified, non interoperable elements. I was hoping to start with the core set, which could have been implemented quickly before solving the much more complicated and delicate problem of supporting totally generic profile elements (and being able to actually do stuff with them).

It became absolutely obvious that we can't agree on a set of simple fields applicable to all wireless groups. Even within groups, reaching a consensus can be very difficult. So the entire generic system had to go in at once.

Setting up profiles

1- Create the necessary content type filters

These are the data types that you can later use in the profiles. T

The format for each Content type filter is a criteria array: an array of functions call performed on the content type. For each one, the method must exist and return true.Format is array(array(callback_funct, array(callback_funct_parameters))

Note that callback_funct is a method of the object to be verified, so it must not have a static classname.

Example: To get Simple content types that are a subclass of file, the array would be

array(array('isSimpleContent'), array('isContentType',array(array('File'))) );

Note the second callback: isContentType, takes a SINGLE parameter, but that parameter is an array. Since the $criteria_array specifies callback parameter as a list, passing 'File' to isContentType is written as array(array('File'))

You'll probably need at least the following filters:

Avatars

array (

array (

'isContentType', array (

array (

'Avatar',

),

),

),

)

Hyperlink only

array (

array (

'isExactContentType', array (

array (

'HyperLink?',

),

),

),

)

SimpleLangstring? only

array (

array (

'isExactContentType', array (

array (

'TrivialLangstring?',

),

),

),

)

SimplePictures?

array (

array (

'isContentType', array (

array (

'SimplePicture?',

),

),

),

)

SimpleString? only

array (

array (

'isExactContentType', array (

array (

'SimpleString?',

),

),

),

)

2- Create a profile template

This is the list of fields available in the profile, as well as optional labels when the user edits them, and when other users view them.

3- Associate the profile template to the network

4- Edit your own profile to test


Data model (only new tables shown)

network_has_profile_templates

  • network_id -- Only one network per profile_field
  • profile_template_id profile_template_id -- The profile template id
  • is_invisible boolean -- If the user wishes to be in anonymous mode.

profile_templates

  • profile_template_id guuid -- The profile id
  • creation_date timestamp

profile_template_fields

Basically a list of data fields (one for each network) that the user can fill. Represented by the ProfileTemplateField? class, which inherits from the abstract ProfileField? class. Used by network administrators to define available fields in user profile.

  • field_id guuid PRIMARY KEY --
  • display_label content_id -- The field's label for the display interface of the profile. Content id, as it must be localizable, and may well actually be an image
  • admin_label content_id -- The field's label for the user's edit interface.
  • content_filter filter_id -- A filter to list the specific content types allowable to be entered as value by the user for this profile field. The UI code for this should live in the ContentTypeFilter? class (the class works, is used elsewhere, but there is no UI for it yet). See the section on ContentTypeFilter?
  • order -- The order in which the field appears in the provile.
  • semantic_id text -- Not user visible. This field has two purposes:
    1. Eventually used to allow export in microformats and XML representation of profiles in microformats or XML formats. For example, for the user's avatar the semantic_id value should be "foaf:nick"
    2. Some semantic_id values will have special meaning to wifidog. For example if an element with foaf:img exists in the profile, it will be used to display the user's custom avatar in the on-line user list. The admin interface to define network profile fields must list all the semantic_id with special wifidog meaning.

user_has_profiles

Used to link the user table with profiles.

  • user_id user_id -- The user's id
  • profile_id profile_id -- The profile id
  • is_invisible boolean -- If the user wishes to be in anonymous mode.

profiles

The profile, represented by the Profile class. Technically, we could directly link the user table in user_profile_fields, but that would be undesirable. The profiles and user_has_profiles tables are used instead for two reasons:

  1. To allow adding a user agreement before creating his profile (once user agreement support is complete
  2. To allow the easy storage of non data elements, such as an invisible mode, wether other users can send the user messages, etc.
  3. To one day allow user's to have one profile for each network, if so desired.
  • profile_id guuid -- The profile id
  • creation_date timestamp

profile_fields

The actual profile values entered by the end user. Represented by the ProfileField? class.

  • template_field_id profile_template_field_id ON DELETE CASCADE ON UPDATE CASCADE
  • field_id guuid PRIMARY KEY
  • content_id content_id -- The actual link to the data
  • last_modified timestamp -- This will probably not be implemented at first, as it requires having the setters and processAdminUI for every content type return if data was actually modified. This is not actually difficult, and is essential if we want to measure how users actually use and update their profile.

ContentTypeFilter?

The ContentTypeFilter? class already exists and is used in several parts of the content manager. Basically, it will call an array of function calls statically on each candidate ContentType?, each with their own array of parameters. Several function in the Content class and it's child have been defined for this purpose. While it's extremely flexible and works very well, currently, the only way to define a filter is from the code (see the documentation in the ContentTypeFilter? constructor). We imperatively need a UI for this as well as a data representation, which will be difficult (hierarchical structure) but not impossible. Difficulties include:

  • Listing the available filter functions (difficulty is compounded by the fact that not all of them are defined in the Content class. Forcing them all to be defined in the Content class with a common prefix could be considered, and would simplify this greatly.
  • Handling the case where an existing filter is invalidated by the disappearance of a filter function in the code, and deleting the field from the filter cleanly.
  • UI for typing in the callback function parameters in a way that can be parsed by PHP without using eval().

Implementation Notes

  • Profile edit interface for end user is implemented in Profile::getAdminAdminUI() and called from User::getAdminUI().
  • Profile fields admin interface for network administrator is called from Network::getAdminUI().