I am attempting to suppress Users with no permissions/roles from our sites.

The user associated contents should be kept on user deletion.

This code below works when the user has a few associated content.

On deletion the content becomes of anonymous author.

It does not work anymore when the user is the author of more than 10 contents. All associated contents are deleted when the user is deleted.

Another method is invoked , i suppose.

How can i solve this?

use Symfony\Component\HttpKernel\Exception\UnauthorizedHttpException;
use \Drupal\user\Entity\User;

function hook_preprocess_page(&$variables, $hook) {    
  $route_name = \Drupal::routeMatch()->getRouteName();
  $user = \Drupal::currentUser();    
  if (count($user->getRoles()) == 1 && ($route_name != "system.401" && $route_name != "user.login")) {
    $userWithoutRole = User::load($user->id());
    if ($userWithoutRole !== null){
      user_cancel([], $user->id(), $method);
    throw new UnauthorizedHttpException('insufficient permissions');

NB: The same issue is remaining on the "auto purge users" module


user_cancel() is run in a batch. This means that either it's called in a form, or batch_process() needs to be called after it. For example, this is the code used from UserController::confirmCancel().

$edit = [
  'user_cancel_notify' => isset($account_data['cancel_notify']) ? $account_data['cancel_notify'] : $this->config('user.settings')->get('notify.status_canceled'),
user_cancel($edit, $user->id(), $account_data['cancel_method']);

// Since user_cancel() is not invoked via Form API, batch processing
// needs to be invoked manually and should redirect to the front page
// after completion.
return batch_process('<front>');

It's not necessary to delete the account, as that is already done from _user_cancel(), the batch operation callback used from user_cancel().

case 'user_cancel_reassign':
case 'user_cancel_delete':
  // Send account canceled notification if option was checked.
  if (!empty($edit['user_cancel_notify'])) {
    _user_mail_notify('status_canceled', $account);
  // …

It's also probable that hook_preprocess_page() is the wrong place to call user_cancel() as it would be called when the page is being rendered, while the batch operations require to redirect users. See batch_process(), which contains the following code.

if (($function = $batch['redirect_callback']) && function_exists($function)) {
  $function($batch_url->toString(), [
    'query' => $query_options,
else {
  return new RedirectResponse($batch_url->setAbsolute()->toString(TRUE)->getGeneratedUrl());
  • Thanks but ...Adding batch_process(); has no effect on my code. If Removing $userWithoutRole->delete(); in my code the user is not deleted. If not hook_preprocess_page(), where ? for what i am trying to achieve ? – Matoeil Apr 14 at 11:34
  • 1
    If the account isn't deleted that means that batch operations aren't run correctly. To be sure the batches run correctly, I would rather use a controller associated to a route. – kiamlaluno Apr 14 at 11:53

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.