Last updated November 18, 2014. Created on February 5, 2008.
Edited by hass, mradcliffe, joshjalopy, axel.rutz. Log in to edit this page.

Impersonating Possibilities

There are many times when you may want your code to "impersonate" another user. An example of this is when a user takes an action that triggers another process. If that other process should be done as a different user then you want to impersonate that other user.

Here is some example code to impersonate another user which is unsafe:

<?php
global $user;
$original_user = $user;

$user = user_load(array('uid' => 1));

// Take your action here where you pretend to be the user with UID = 1 (typically the admin user on a site)
// NOTE: - this is the unsafe part - if your code here fails, then the user suddenly has the permissions of UID 1!
$user = $original_user;
?>

The safe way to implement this is to use the function session_save_session() (D6) or drupal_save_session() (D7) as follows:

For D6:

<?php
global $user;
$original_user = $user;
$old_state = session_save_session();
session_save_session(FALSE);
$user = user_load(array('uid' => 1));

// Take your action here where you pretend to be the user with UID = 1 (typically the admin user on a site)
// If your code fails, it's not a problem because the session will not be saved
$user = $original_user;
session_save_session($old_state);

// From here on the $user is back to normal so it's OK for the session to be saved
?>

For D7:

<?php
global $user;
$original_user = $user;
$old_state = drupal_save_session();
drupal_save_session(FALSE);
$user = user_load(1);

// Take your action here where you pretend to be the user with UID = 1 (typically the admin user on a site)
// If your code fails, it's not a problem because the session will not be saved
$user = $original_user;
drupal_save_session($old_state);

// From here on the $user is back to normal so it's OK for the session to be saved
?>

For D8:

You may use the Account Switcher (account_switcher) service to safely impersonate another user. This service will handle the session writing that was required in Drupal 6 and Drupal 7 above.

In Drupal 8, the core Cron service will always execute as an anonymous user when it invokes cron handlers and processes queues.

<?php
 
// Retrieve the account switcher service. Ideally you should inject the account_switcher service into your class.
 
$accountSwitcher = Drupal::service('account_switcher');
 
$accountSwitcher->switchTo(new Drupal\Core\Session\AnonymousUserSession());
 
 
// Take your action here. If your code fails, then you should catch an exception
  // and switch back (see below).

  // Restore user account.
 
$accountSwitcher->switchBack();
?>

or

<?php
 
// Retrieve the account switcher service. Ideally you should inject the account_switcher service into your class.
 
$accountSwitcher = Drupal::service('account_switcher');
 
$accountSwitcher->switchTo(new UserSession(array('uid' => 2)));
 
 
// Take your action here. If your code fails, then you should catch an exception
  // and switch back (see below).

  // Restore user account.
 
$accountSwitcher->switchBack();
?>

An alternative to the above that is related to Menu Tree access is to use a Menu Link Tree Manipulator service. Manipulators allow you to modify or transform a given menu tree by a callable method. This would allow you, for instance, to change a give menu tree by a particular user.

<?php
 
// Setup manipulators array to pass into the MenuTree transform method that
  // includes your module's manipulator service and method.
 
$manipulators = array(
   
'callable' => 'my_module.tree_manipulator_service::checkAccess',
  );
 
 
// Menu parameters
 
$parameters = new MenuTreeParameters();

 
// Transform the menu tree after loading the main menu.
 
$menu_tree = Drupal::service('menu.link_tree');
 
$tree = $menu_tree->load('main', $parameters);
 
$tree = $menu_tree->transform($tree, $manipulators);
?>

Looking for support? Visit the Drupal.org forums, or join #drupal-support in IRC.

Comments

j_ten_man’s picture

D7 version is incorrect...Should be almost the same as D6:

<?php
global $user;
$original_user = $user;
$old_state = drupal_save_session();
drupal_save_session(FALSE);
$user = user_load(1);

// Take your action here where you pretend to be the user with UID = 1 (typically the admin user on a site)
// If your code fails, it's not a problem because the session will not be saved
$user = $original_user;
drupal_save_session($old_state);

// From here on the $user is back to normal so it's OK for the session to be saved
?>
ErnestoJaboneta’s picture

I wanted to use this with rules, so that when Cron ran a scheduled rule, it would run as a user with correct access. Luckily I found this page to help me. Just thought I'd share how, in case anyone needs it. Note the global at the beginning so that both scripts have access to the same variables.

Add this custom php at beginning of rule, before your actions.

<?php
global $user,$original_user,$old_state;
$original_user = $user;
$old_state = drupal_save_session();
drupal_save_session(FALSE);
$user = user_load(1);

?>

Add this custom php at end of rule, after your actions.

<?php
global $user,$original_user,$old_state;
$user = $original_user;
drupal_save_session($old_state);

// From here on the $user is back to normal so it's OK for the session to be saved
?>
kojis’s picture

Thanks for this, it was the only solution which worked for me! Trying to have cron triggered rules (+components) using ultimate cron.

jfew’s picture

D7 cron is really not fit for purpose. Rules scheduler does not make sense to me; it is not intuitive. So I am forced to use PHP code and Cron.

I have tried to replace Cron with Elysia Cron and Croninfinite but both did not work. I simply want a scheduler to run a rule at a certain time daily. These two modules allowed me to select a specific time, but when the time came for them to run the rule, nothing happened. Maybe its because I am using v7.0 of Drupal, as it seems they work others.

I reverted to Cron in core and lo and behold it had its own idiosyncracies:
* it runs under anonymous user, when most of things one will do a rule for need admin privileges. Thanks therefore for these two snippets of code. I am trying them now.
* it allows you to set schedules such as every 3hrs, every hour, yet it may or may not run depending on visits to the website.
* it seems that even if visits to the site are constant it will not run exactly every 3hrs or exactly every hour.

ErnestoJaboneta’s picture

It sounds like you might not have cron set up properly. You need to have a cron job set up to execute Drupal's cron regularly. See Configuring cron jobs using the cron command. If you need things executed at an exact time, you need to set the cron job to run every minute. Without doing this, yes, your site will only run cron when you have visitors.

jfew’s picture

Thanks for the link. The info will help a lot.

Countzero’s picture

Thanks a million for this snippet. It just saved my life. Well, almost.

Matt Habermehl’s picture

I had tried Views Bulk Operations, Rules Bonus, and Views Rules to try to get my rules to work and I was banging my head off the desk at 2am. This saved the project. Thank you so much!