Clearing User Session Data

When making changes to a user’s status or capabilities, as we diMODX logoscussed in the previous article, sometimes you’d like the changes to take effect right away. Suppose, for example, that a user selects an option that adds them to a particular user group. It’s frustrating to find that the users have to log out, then log back in before MODX will treat them as members of the group.

Adding a user to a user group can have many ripple effects. It may qualify the user for one or more new permission ACL entries, which would mean more permissions for the user (potentially, both context and object permissions). It might give the user access to resources in protected resource groups,elements in protected categories, or new Media Sources. There may also be snippets that check the user’s status with $user->isMember().

In this article, we’ll look ways to force MODX to update the user’s status immediately. Susan Sottwell played an important role in testing the code below.

The Problem

You may have experienced problems with changes on your site not taking effect due to the cache. That’s not what we’re talking about here, though. Clearing the site cache often won’t help with updating a users’ status. That’s because much of the user’s information is held in the $_SESSION array. You could fix things by unsetting the $_SESSION array, but that would be a little like killing a mosquito with a sledge hammer. Deleting the _$SESSION effectively logs the user out and forces them to log back in, which is what we’re trying to avoid.

The Solution

The short answer is to refresh the user’s data with $user->loadAttributes(), though in some cases it requires an extra step. Here’s our code from the previous article with some extra lines that will make the change take effect immediately.

[code language=”php”]
$groupname = ‘Group1’;
if(!($modx->user->isMember($groupname))) {

/* New Code */
$userId = $modx->user->get(‘id’);
$context = ‘web’;
$principalTargets = $modx->getOption(‘principal_targets’, null, ‘modAccessContext,
$targets = explode(‘,’, $principalTargets);
array_walk($targets, ‘trim’);

$modx->user->loadAttributes($targets, $context, true);

How it Works

The code could be made more efficient, but this version is a little easier to understand. Lets look first at the loadAttributes() call. It takes three arguments.

The first argument is an array of permission-related classes that should be refreshed for the user ($principalTargets). Our code uses $modx->getOption() to retrieve the principal_targets System Setting. If it’s not set, we include a set of defaults that will take care of most situations: modAccessContext, modAccessResourceGroup, modAccessCategory, sources.modAccessMediaSource. These four (which make up the default value of the principal_targets System Setting) will cover refreshing the user’s access to the context, resource groups, categories, and Media Sources.

After the getOption() line runs, the targets will be a string containing a comma-separated list. We need it to be an array (that’s what loadAttributes is expecting), so we convert it to one with explode(), which also removes the commas. To finish off the first argument, we use array_walk() to call the trim() function on each member of the array. The trim() function removes any leading or trailing spaces, newlines, or tabs.

It’s not actually necessary to check the System Setting with getOption(). If you know which targets you need, you can speed things up slightly by just doing something like this:

[code language=”php”]
$targets = array(‘modAccessResourceGroup’, ‘modAccessCategory’);

The second argument to loadAttributes() is the context you want to be refreshed. This is usually ‘web’, but it could be another front-end context. This argument only takes a single context, but usually, you only need it to take effect in one context. If necessary, you could call loadAttributes() multiple times, once for each context.

If you have a multi-context site and the code could run in more than one front-end context, you can reload the user attributes for the current context by changing the $context = line to this:

[code language=”php”]
$context = $modx->context->get(‘key’);

The third argument, if set to true, tells MODX that you want things reloaded from scratch rather than from the cache.

Once we have the three arguments set up, we call loadAttributes() with them to refresh the user's data.

What’s That Thing with the $_SESSION

There’s a minor bug in MODX (possibly fixed by the time you read this) that keeps the data from being completely refreshed. If you call user->joinGroup(), for example, that method clears a user $_SESSION variable called modx.user.##.userGroupNames (where ## is the user’s ID). At this writing, if you check the user’s group membership with $user->getUserGroups() right after calling joinGroup(), the user won’t be a member yet because getUserGroups() checks this variable: $_SESSION["modx.user.##.userGroups"], which isn’t cleared by joinGroup().

To handle this problem, we’ve added this line to the code to clear the other $_SESSION variable:

[code language=”php”]

I filed a pull request to fix this bug, so there’s a good chance that it will have been fixed by the time you read this, in which case that line is no longer necessary, though it won’t hurt anything to have it there.

Wrapping Up

Once we’ve cleared the user’s data with the code above, as soon as a method like isMember(), getGroups(), or hasPermission() is called, the data will be reloaded fresh from the database and the user will have the access they deserve.

For more information on how to use MODX to create a web site, see my web site Bob’s Guides, or better yet, buy my book: MODX: The Official Guide.

Looking for quality MODX Web Hosting? Look no further than Arvixe Web Hosting!

Tags: , , , | Posted under MODX, MODX | RSS 2.0

Author Spotlight

Bob Ray

Bob Ray is the author of MODX: The Official Guide and over 30 MODX add-on components. He hosts Bob's Guides, a source of valuable information for MODX users, and has been very active in the MODX Forums with over 19,000 posts.

Leave a Reply

Your email address will not be published. Required fields are marked *