User set "Blocked After" date automatically

Is there a way to set a users Blocked After date automatically through a plugin on save?

So I want to create or update a user and set the date when it’s set to active (Blocked Until) and then after saving the user, it should automatically fill in the Blocked After date set to say 30 days after the activation date. Ideally I would like to fetch a number in the users comments field and use that as number of days which should be added, but I would like to know first if something like this is possible in general.

I’m also aware that it’s not too difficult to add those dates by hand but I would like to reduce the work during user creation and updating as much as possible.

This should be possible if you create a plugin that runs on the event OnUserFormSave (or maybe ‘OnBeforeUserFormSave’).

Keep in mind that blockeduntil is a field of modUserProfile and not modUser.

You may also have to experiment to see whether to use a timestamp or a human-readable date when using set() on that field. My guess is the latter, but I could definitely be wrong.

IIRC, the field is stored as a timestamp, but set() wants what you use when you set it in the Manager.

Thanks for all the valuable hints! I think I have a general idea of what I have to do. How do I retreive a field from the profile I’m currently editing (and not the one from the current logged in user), though?

I found $modx->getUser(); but that’s not what I need here, I guess.

In the Plugin, the variable $user gives you access to the user that was edited. Then with

$profile = $user->getOne('Profile');

you should be able to access the user profile.

Thank you! So I’m trying to start simple here and just get the users email to see if and how it’s working, but it doesn’t seem to right now. Am I missing something?

$profile = $user->getOne('Profile');
$email = $profile->get('email');
$modx->log(modX::LOG_LEVEL_ERROR, 'EMAIL: ' . $email );

This code works on my installation. Did you set the right system event for your plugin?

It’s firing OnUserProfileSave and if I place a log message in the first line of the plugin, I get that, but nothing after that.

I notice a few different errors in the log, too:

...core/xpdo/xpdo.class.php : 1320) Could not get table class for class: modAccess
...core/xpdo/xpdo.class.php : 1289) Could not get table name for class: modAccess
...core/xpdo/om/xpdoobject.class.php : 240) Error 42000 executing statement: 
Array
(
    [0] => 42000
    [1] => 1064
    [2] => You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'AS `modAccess` WHERE `modAccess`.`principal` = 10' at line 1
)

Not sure if those are related, though…

I believe this event doesn’t have a $user variable. Try $userprofile instead.
Or use the event “OnUserFormSave” like I suggested above.

My bad, I didn’t notice the Profile instead of the Form :man_facepalming: Works now!

I got a working solution! Turns out set() wants a timestamp after all @bobray, but thank you for the input! Also the plugin needs to run OnBeforeUserFormSave in order to fill in the blockeduntil field.

Here’s my code, any improvements or suggestions are very welcome!

// get edited profile
$profile = $user->getOne('Profile');

// get starting date
$blockeduntil = $profile->get('blockeduntil');

// proceed if blockeduntil is set
if ($blockeduntil != '') {
  
  // get comment field value
  $comment = $profile->get('comment');
  
  // if comment is not empty add value as number of days and make sure it's int and converted as timestamp
  if ($comment != '') {
    $blockedafter = $blockeduntil + (intval(preg_replace('/[^0-9]/', '', $comment))) * 86400;
  }
  
  // set blockedafter date
  $profile->set('blockedafter', $blockedafter);
  
}

The event “OnUserFormSave” should work too, but you have to call save() yourself.

$profile->save();

One thing to keep in mind (not sure if it affects your case) is that sometimes the value of blockeduntil gets set by the system automatically. Namely after 5 failed login attempts (system setting [[++failed_login_attempts]]) for 60 minutes into the future ([[++blocked_minutes]]).

Is there an advantage using one event over the other?

If the value gets set by the system, will that trigger the plugin as well? In that case it would be an issue, but if it doesn’t fire the event, it should be fine I guess…

In the “Before Save” event you can prevent the user from being saved. (For example you could check that the value in the field ‘comment’ is a number and prevent saving if it is not).

No, it shouldn’t fire this event.


Your code can generate the error “Attempt to set NOT NULL field blockedafter to NULL” , so you should move the set()-line into the if-block.

if ($comment != '') {
	$blockedafter = $blockeduntil + (intval(preg_replace('/[^0-9]/', '', $comment))) * 86400;
	// set blockedafter date
	$profile->set('blockedafter', $blockedafter);
}
1 Like

This topic was automatically closed 2 days after discussion ended and a solution was marked. New replies are no longer allowed. You can open a new topic by clicking the link icon below the original post or solution and selecting “+ New Topic”.