Basic idea:

An API that allows to save user level settings, identified by a string.

Stuff to think about:
- Also store the default value in that table, for example by using the (u)id 0
- Allow multiple levels of defaults, for example for roles.
- How much of the default handling could the get function handle automatically? Maybe default to check for uid < role ids < global default and optionally allow to pass in a type => array(keys) mapping which overrides the default?

Two API functions:
privatemsg_get_setting()
privatemsg_set_setting()

The arguments depend on what this supports, most basic version:
get ($setting, $uid = NULL)
set($setting, $value, $uid = NULL)

To support the suggestion above, it could look like this:
get($setting, $ids)
$ids would per default be like this:
array(
'user' => array($account->uid),
'role' => array_keys($account->roles)
'global' => array(0)
)

We can also rely on our query builder for special cases.
set($setting, $value, $type, $id)

Schema:
pm_settings
uid, int (maybe type + id instead to support different levels of defaults)
setting, varchar
value, int (or do we want a serialized string, similar to {variable}?)

Thoughts, suggestions, ideas?

Support from Acquia helps fund testing for Drupal Acquia logo

Comments

Berdir’s picture

Status: Active » Needs review
FileSize
13.58 KB

Ok, here is a first patch, i implemented the fancy version...

API functions:

function privatemsg_get_setting($setting, $ids = NULL) {}
function privatemsg_set_setting($type, $id, $setting, $value) {}
function privatemsg_del_setting($type, $id, $setting) {}

$ids = function privatemsg_get_default_setting_ids($account = NULL) {}

The first three should be obvious, the last extracts the default ids off a user object (defaults to the current user and privatemsg_get_setting() does too).

Here is an extract from the tests to see how it can be used.

    // Create some global and role default settings.
    privatemsg_set_setting('global', 0, 'test', 1);
    privatemsg_set_setting('role', array_pop(array_keys($user->roles)), 'test', 2);

    // Add some user specific setting.
    privatemsg_set_setting('user', $admin->uid, 'test', 3);
    privatemsg_set_setting('user', $user->uid, 'test2', 4);
    privatemsg_set_setting('user', $user2->uid, 'test2', -1);

    // Get the ids for each user.
    $admin_ids = privatemsg_get_default_setting_ids($admin);
    $user_ids = privatemsg_get_default_setting_ids($user);
    $user2_ids = privatemsg_get_default_setting_ids($user2);

    $this->assertEqual(privatemsg_get_setting('test', $admin_ids), 3, t('The admin has a user level setting.'));
    $this->assertEqual(privatemsg_get_setting('test', $user_ids), 2, t('The first user has role-level default.'));
    $this->assertEqual(privatemsg_get_setting('test', $user2_ids), 1, t('The second user defaults to the global.'));

What is implemented:
- The API :)
- A rather intelligent (I hope) and well tested (I think) static cache mechanism that works like this: 1. Look in cache for most specific type (first in array), 2. try to load not-yet-loaded settings for all types/ids, 3. go through all types/ids and return the first match. This means that the order of types in the $ids array indicates their weight/importance.
- Schema including update functions
- Disabled is ported to this API (There is still privatemsg_is_disabled() because that one does the user_load() and permission check). Existing disabled settings are not being ported yet.
- There are rather good tests for it.

TODO/Questions:
- Api docs
- Would it be useful to make the implementation configurable? (think cache.inc)
- Currently, only integers are supported, should we switch to serialized string instead? (Might make it possible to port more configurations like the role-based blocking rules to it but would slow it down)
- I forgot all other questions I had, too tired.

Please test and review!

litwol’s picture

Status: Needs review » Needs work

Why &_privatemsg_setting_static_cache() and not &drupal_static('pmsg_static_cache_key', array()) ?

Berdir’s picture

Because this is Drupal 6 :)

litwol’s picture

Version: 6.x-2.x-dev » 7.x-1.x-dev

imho new features need to be developed against latest and the greatest (d7) and back-ported if necessary. Not the other way around. not to mention as i already pointed out some tools are already implemented in d7, by working on new features there you have the luxury of learning of the new tools first rather than reinventing :). Not saying you didn't, i'm saying others might not be as thorough.

Berdir’s picture

You are right, but...

- 7.x-1.x is stable. To add new features to 7.x, I first need to start a 7.x-2.x branch. Therefore, I'm currently using 6.x-2.x as the development branch.

- This feature is a dependency for #967164: E-mails not sent if message was sent to role members, which is currently targeted against 6.x-2.x too

I will start a 7.x-2.x branch sooner or later, not sure about the process yet (not the technical part...)

BenK’s picture

Version: 7.x-1.x-dev » 6.x-2.x-dev

Subscribing to help with testing.

BenK’s picture

I tried applying the patch in #1 using "git apply" but it didn't work. Error said:

error: patch failed: privatemsg.module:2763
error: privatemsg.module: patch does not apply

Does this need a re-roll?

--Ben

Berdir’s picture

Status: Needs work » Needs review
FileSize
14 KB
BenK’s picture

Status: Needs review » Needs work

Hey Berdir,

I'm not exactly sure how to test this patch, but I applied it successfully. However, when browsing around the site, I'm now getting the following notice:

user warning: Table 'd6tod7.pm_setting' doesn't exist query: SELECT pms.type, pms.id, pms.value FROM pm_setting pms WHERE (pms.setting = 'disabled') AND ((pms.type = 'user' AND pms.id IN (1)) OR (pms.type = 'role' AND pms.id IN (2)) OR (pms.type = 'global' AND pms.id IN (0))) in /Users/benkaplan/git/drupal-6.20dev/sites/all/modules/privatemsg/privatemsg.module on line 2925.

Also, update.php didn't indicate any updates to run.

Let me know what else you need in the way of testing. As I understand it, most of what we need this patch for is in other issues (like the e-mail notifications for messages to roles).

--Ben

Berdir’s picture

There is an update function with the number 6205(). It is possible that an update with this name was already run when you tested another issue (most likely the pm_thread one, which adds update functions too).

So to be able to test this patch, you need to directly set back the schema_version information in {system} to 6204 for privatemsg. The following query should work:

UPDATE system SET schema_version = 6204 WHERE name = 'privatemsg'

Berdir’s picture

Status: Needs work » Needs review
FileSize
14.51 KB

Ok, can you retry the update with this patch?

Remember that you probably will have to re-run the update query from above.

Berdir’s picture

Forgot the update the schema definition in the update function.

BenK’s picture

Status: Needs review » Reviewed & tested by the community

Latest patch worked great so this is RTBC! :-)

--Ben

Berdir’s picture

Version: 6.x-2.x-dev » 7.x-2.x-dev
Status: Reviewed & tested by the community » Patch (to be ported)

Ok, commited!

I'm not sure if I will do a straight port of this to D7 or instead make this a separate module.

Berdir’s picture

Version: 7.x-2.x-dev » 6.x-2.x-dev
Status: Patch (to be ported) » Needs review
FileSize
5.8 KB

Updated patch for 6.x-2.x.

Contains support for a default argument and variable_get() fallback. Also contains the update function to migrate existing settings, which I forgot above.

Status: Needs review » Needs work

The last submitted patch, defaults_and_upgrade.patch, failed testing.

Berdir’s picture

Status: Needs work » Needs review
FileSize
5.83 KB

Bugfix for the above patch, this should work.

Berdir’s picture

Version: 6.x-2.x-dev » 7.x-2.x-dev
Status: Needs review » Patch (to be ported)

Commited, ack to 7.x-2.x!

Berdir’s picture

Status: Patch (to be ported) » Fixed

Commited to 7.x-2.x.

Status: Fixed » Closed (fixed)

Automatically closed -- issue fixed for 2 weeks with no activity.