summaryrefslogtreecommitdiffstatshomepage
path: root/core/modules/user/user.api.php
blob: 5a03c36d896e272ecb2dfaaef7bc779bcf7ea0a0 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
<?php

/**
 * @file
 * Hooks provided by the User module.
 */

use Drupal\Core\Session\AccountInterface;
use Drupal\user\UserInterface;

/**
 * @addtogroup hooks
 * @{
 */

/**
 * Act on user account cancellations.
 *
 * This hook is invoked from user_cancel() before a user account is canceled.
 * Depending on the account cancellation method, the module should either do
 * nothing, unpublish content, or anonymize content. See user_cancel_methods()
 * for the list of default account cancellation methods provided by User module.
 * Modules may add further methods via hook_user_cancel_methods_alter().
 *
 * This hook is NOT invoked for the 'user_cancel_delete' account cancellation
 * method. To react to that method, implement hook_ENTITY_TYPE_predelete() or
 * hook_ENTITY_TYPE_delete() for user entities instead.
 *
 * Expensive operations should be added to the global account cancellation batch
 * by using batch_set().
 *
 * @param array $edit
 *   The array of form values submitted by the user.
 * @param \Drupal\user\UserInterface $account
 *   The user object on which the operation is being performed.
 * @param string $method
 *   The account cancellation method.
 *
 * @see user_cancel_methods()
 * @see hook_user_cancel_methods_alter()
 */
function hook_user_cancel($edit, UserInterface $account, $method): void {
  switch ($method) {
    case 'user_cancel_block_unpublish':
      // Unpublish nodes (current revisions).
      \Drupal::moduleHandler()->loadInclude('node', 'inc', 'node.admin');
      $nodes = \Drupal::entityQuery('node')
        ->accessCheck(FALSE)
        ->condition('uid', $account->id())
        ->execute();
      node_mass_update($nodes, ['status' => 0], NULL, TRUE);
      break;

    case 'user_cancel_reassign':
      // Anonymize nodes (current revisions).
      \Drupal::moduleHandler()->loadInclude('node', 'inc', 'node.admin');
      $nodes = \Drupal::entityQuery('node')
        ->accessCheck(FALSE)
        ->condition('uid', $account->id())
        ->execute();
      node_mass_update($nodes, ['uid' => 0], NULL, TRUE);
      // Anonymize old revisions.
      \Drupal::database()->update('node_field_revision')
        ->fields(['uid' => 0])
        ->condition('uid', $account->id())
        ->execute();
      break;
  }
}

/**
 * Modify account cancellation methods.
 *
 * By implementing this hook, modules are able to add, customize, or remove
 * account cancellation methods. All defined methods are turned into radio
 * button form elements by user_cancel_methods() after this hook is invoked.
 * The following properties can be defined for each method:
 * - title: The radio button's title.
 * - description: (optional) A description to display on the confirmation form
 *   if the user is not allowed to select the account cancellation method. The
 *   description is NOT used for the radio button, but instead should provide
 *   additional explanation to the user seeking to cancel their account.
 * - access: (optional) A boolean value indicating whether the user can access
 *   a method. If 'access' is defined, the method cannot be configured as
 *   default method.
 *
 * @param array $methods
 *   An array containing user account cancellation methods, keyed by method id.
 *
 * @see user_cancel_methods()
 * @see \Drupal\user\Form\UserCancelForm
 */
function hook_user_cancel_methods_alter(&$methods) {
  $account = \Drupal::currentUser();
  // Limit access to disable account and unpublish content method.
  $methods['user_cancel_block_unpublish']['access'] = $account->hasPermission('administer site configuration');

  // Remove the content re-assigning method.
  unset($methods['user_cancel_reassign']);

  // Add a custom zero-out method.
  $methods['my_module_zero_out'] = [
    'title' => t('Delete the account and remove all content.'),
    'description' => t('All your content will be replaced by empty strings.'),
    // Access should be used for administrative methods only.
    'access' => $account->hasPermission('access zero-out account cancellation method'),
  ];
}

/**
 * Alter the username that is displayed for a user.
 *
 * Called by $account->getDisplayName() to allow modules to alter the username
 * that is displayed. Can be used to ensure user privacy in situations where
 * $account->getDisplayName() is too revealing. This hook is invoked both for
 * user entities and the anonymous user session object.
 *
 * @param string|Drupal\Component\Render\MarkupInterface $name
 *   The username that is displayed for a user. If a hook implementation changes
 *   this to an object implementing MarkupInterface it is the responsibility of
 *   the implementation to ensure the user's name is escaped properly. String
 *   values will be autoescaped.
 * @param \Drupal\Core\Session\AccountInterface $account
 *   The object on which the operation is being performed. This object may be a
 *   user entity. If the object is an implementation of UserInterface you can
 *   use instanceof operator before accessing user entity methods. For example:
 *   @code
 *   if ($account instanceof UserInterface) {
 *      // Access user entity methods.
 *   }
 *   @endcode
 *
 * @see \Drupal\Core\Session\AccountInterface::getDisplayName()
 * @see sanitization
 */
function hook_user_format_name_alter(&$name, AccountInterface $account) {
  // Display the user's uid instead of name.
  if ($account->id()) {
    $name = t('User @uid', ['@uid' => $account->id()]);
  }
}

/**
 * The user just logged in.
 *
 * @param \Drupal\user\UserInterface $account
 *   The user object on which the operation was just performed.
 */
function hook_user_login(UserInterface $account): void {
  $config = \Drupal::config('system.date');
  // If the user has a NULL time zone, notify them to set a time zone.
  if (!$account->getTimezone() && $config->get('timezone.user.configurable') && $config->get('timezone.user.warn')) {
    \Drupal::messenger()
      ->addStatus(t('Configure your <a href=":user-edit">account time zone setting</a>.', [
        ':user-edit' => $account->toUrl('edit-form', [
          'query' => \Drupal::destination()
            ->getAsArray(),
          'fragment' => 'edit-timezone',
        ])->toString(),
      ]));
  }
}

/**
 * The user just logged out.
 *
 * @param \Drupal\Core\Session\AccountInterface $account
 *   The user object on which the operation was just performed.
 */
function hook_user_logout(AccountInterface $account): void {
  \Drupal::database()->insert('logouts')
    ->fields([
      'uid' => $account->id(),
      'time' => time(),
    ])
    ->execute();
}

/**
 * @} End of "addtogroup hooks".
 */