Newer
Older
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
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
<?php
/**
* @file
* Provides token-based name displays for users.
*
* @todo Add a 'view realname' permission enabled by default
* @todo Allow users to login with their real name
* @todo Disable the username field
*/
use Drupal\Component\Utility\Html;
use Drupal\Component\Utility\Unicode;
use Drupal\Core\Entity\Display\EntityViewDisplayInterface;
use Drupal\Core\Entity\EntityInterface;
use Drupal\Core\Link;
use Drupal\Core\Routing\RouteMatchInterface;
use Drupal\Core\Url;
use Drupal\user\Entity\User;
/**
* @defgroup realname Real name API
*/
/**
* Implements hook_help().
*/
function realname_help($route_name, RouteMatchInterface $route_match) {
switch ($route_name) {
// Main module help for the Realname module.
case 'realname.admin_settings_form':
case 'help.page.realname':
return '<p>' . t("A Real Name is what the site developer decides that users' names should look like. It is constructed from various tokens that are available within the site.") . '</p>';
}
}
/**
* Implements hook_entity_extra_field_info().
*/
function realname_entity_extra_field_info() {
$fields['user']['user']['display']['realname'] = [
'label' => t('Real name'),
'description' => t('Real name'),
'weight' => -1,
'visible' => FALSE,
];
return $fields;
}
/**
* Implements hook_user_format_name_alter().
*/
function realname_user_format_name_alter(&$name, $account) {
static $in_username_alter = FALSE;
$uid = $account->id();
// Don't alter anonymous users or objects that do not have any user ID.
if (empty($uid)) {
return;
}
// Real name was loaded/generated via hook_user_load(), so re-use it.
if (isset($account->realname)) {
if (Unicode::strlen($account->realname)) {
// Only if the real name is a non-empty string is $name actually altered.
$name = $account->realname;
}
return;
}
// Real name was not yet available for the account so we need to generate it.
// Because tokens may call format_username() we need to prevent recursion.
if (!$in_username_alter) {
$in_username_alter = TRUE;
// If $account->realname was undefined, then the user account object was
// not properly loaded. We must enforce calling user_load().
if ($realname_account = User::load($uid)) {
realname_user_format_name_alter($name, $realname_account);
}
$in_username_alter = FALSE;
}
}
/**
* Implements hook_ENTITY_TYPE_load().
*/
function realname_user_load(array $accounts) {
$realnames = realname_load_multiple($accounts);
foreach ($realnames as $uid => $realname) {
$accounts[$uid]->realname = $realname;
}
}
/**
* Implements hook_ENTITY_TYPE_update().
*/
function realname_user_update(EntityInterface $account) {
// Since user data may have changed, update the realname and its cache.
$realnames = &drupal_static('realname_load_multiple', []);
$realnames[$account->id()] = realname_update($account);
}
/**
* Implements hook_ENTITY_TYPE_delete().
*/
function realname_user_delete(EntityInterface $account) {
realname_delete($account->id());
}
/**
* Implements hook_ENTITY_TYPE_view() for user entities.
*/
function realname_user_view(array &$build, EntityInterface $account, EntityViewDisplayInterface $display, $view_mode) {
if ($display->getComponent('realname')) {
if ($account->access('view')) {
$url = Url::fromRoute('entity.user.canonical', ['user' => $account->id()]);
$markup = Link::fromTextAndUrl($account->realname, $url)->toString();
}
else {
$markup = Html::escape($account->realname);
}
$build['realname'] = [
'#theme' => 'field',
'#title' => t('Real name'),
'#label_display' => 'inline',
'#view_mode' => '_custom',
'#field_name' => 'realname',
'#field_type' => 'text',
'#field_translatable' => FALSE,
'#entity_type' => 'custom',
'#bundle' => 'custom',
'#object' => $account,
'#items' => [TRUE],
'#is_multiple' => FALSE,
0 => [
'#markup' => $markup,
],
];
}
}
/**
* @addtogroup realname
* @{
*/
/**
* Loads a real name.
*
* @param Drupal\user\Entity\User $account
* A user account object.
*
* @return mixed
* The user's generated real name.
*/
function realname_load(User $account) {
$realnames = realname_load_multiple([$account->id() => $account]);
return reset($realnames);
}
/**
* Loads multiple real names.
*
* @param array $accounts
* An array of user account objects keyed by user ID.
*
* @return array
* An array of real names keyed by user ID.
*/
function realname_load_multiple(array $accounts) {
$realnames = &drupal_static(__FUNCTION__, []);
if ($new_accounts = array_diff_key($accounts, $realnames)) {
// Attempt to fetch realnames from the database first.
$realnames += \Drupal::database()->query("SELECT uid, realname FROM {realname} WHERE uid IN (:uids[])", [':uids[]' => array_keys($new_accounts)])->fetchAllKeyed();
// For each account that was not present in the database, generate its
// real name.
foreach ($new_accounts as $uid => $account) {
if (!isset($realnames[$uid])) {
$realnames[$uid] = realname_update($account);
}
}
}
return array_intersect_key($realnames, $accounts);
}
/**
* Update the realname for a user account.
*
* @param Drupal\user\Entity\User $account
* A user account object.
*
* @return string
* A string with the real name.
*
* @see hook_realname_pattern_alter()
* @see hook_realname_alter()
* @see hook_realname_update()
*/
function realname_update(User $account) {
$realname = '';
if (!$account->isAnonymous()) {
// Get the default pattern and allow other modules to alter it.
$config = \Drupal::config('realname.settings');
$pattern = $config->get('pattern');
\Drupal::moduleHandler()->alter('realname_pattern', $pattern, $account);
// Perform token replacement on the real name pattern.
$realname = \Drupal::token()->replace($pattern, ['user' => $account], ['clear' => TRUE, 'sanitize' => FALSE]);
// Remove any HTML tags.
$realname = strip_tags(Html::decodeEntities($realname));
// Remove double spaces (if a token had no value).
$realname = preg_replace('/ {2,}/', ' ', $realname);
// Allow other modules to alter the generated realname.
\Drupal::moduleHandler()->alter('realname', $realname, $account);
// The name must be trimmed to 255 characters before inserting into the
// database.
$realname = Unicode::truncate(trim($realname), 255);
}
else {
// DisplayName cannot generated with tokens for anonymous users.
$realname = $account->label();
}
// Save to the database and the static cache.
\Drupal::database()->merge('realname')
->key(['uid' => $account->id()])
->fields([
'realname' => $realname,
'created' => \Drupal::time()->getRequestTime(),
])
->execute();
// Allow modules to react to the realname being updated.
\Drupal::moduleHandler()->invokeAll('realname_update', [$realname, $account]);
// Clear the entity cache.
/** @var \Drupal\user\UserStorageInterface $user_storage */
$user_storage = \Drupal::getContainer()->get('entity.manager')->getStorage('user');
$user_storage->resetCache([$account->id()]);
return $realname;
}
/**
* Delete a real name.
*
* @param int $uid
* A user ID.
*/
function realname_delete($uid) {
return realname_delete_multiple([$uid]);
}
/**
* Delete multiple real names.
*
* @param array $uids
* An array of user IDs.
*/
function realname_delete_multiple(array $uids) {
\Drupal::database()->delete('realname')->condition('uid', $uids, 'IN')->execute();
drupal_static_reset('realname_load_multiple');
\Drupal::entityTypeManager()->getStorage('user')->resetCache($uids);
}
/**
* Delete all real names.
*/
function realname_delete_all() {
\Drupal::database()->truncate('realname')->execute();
drupal_static_reset('realname_load_multiple');
\Drupal::entityTypeManager()->getStorage('user')->resetCache();
}
/**
* @} End of "addtogroup realname".
*/