Commit 1d1fe197 authored by webchick's avatar webchick

Issue #2112679 by Berdir, damiankloip, nlisgo, krlucas, lokapujya, m1r1k,...

Issue #2112679 by Berdir, damiankloip, nlisgo, krlucas, lokapujya, m1r1k, piyuesh23, blueminds, stefan.r, subhojit777, dawehner, kerby70, Dustin LeBlanc, znerol, JeroenT, borisson_, scor, amitgoyal, s_leu: getUsername() should return the username getDisplayName() for the formatted user name
parent 1a37b092
......@@ -1961,7 +1961,7 @@ function hook_mail($key, &$message, $params) {
$context = $params['context'];
$variables = array(
'%site_name' => \Drupal::config('system.site')->get('name'),
'%username' => user_format_name($account),
'%username' => $account->getDisplayName(),
);
if ($context['hook'] == 'taxonomy') {
$entity = $params['entity'];
......
......@@ -314,7 +314,7 @@ function drupal_get_path($type, $name) {
* names or link URLs into translated text. Variable substitution looks like
* this:
* @code
* $text = t("@name's blog", array('@name' => user_format_name($account)));
* $text = t("@name's blog", array('@name' => $account->getDisplayName()));
* @endcode
* Basically, you can put variables like @name into your string, and t() will
* substitute their sanitized values at translation time. (See the
......
......@@ -106,19 +106,49 @@ public function getPreferredLangcode($fallback_to_default = TRUE);
public function getPreferredAdminLangcode($fallback_to_default = TRUE);
/**
* Returns the username of this account.
* Returns the unaltered login name of this account.
*
* @return string
* An unsanitized plain-text string with the name of this account that is
* used to log in. Only display this name to admins and to the user who owns
* this account, and only in the context of the name used to login. For
* any other display purposes, use
* \Drupal\Core\Session\AccountInterface::getDisplayName() instead.
*
* @deprecated in Drupal 8.0.0, will be removed before Drupal 9.0.0.
* Use \Drupal\Core\Session\AccountInterface::getAccountName() or
* \Drupal\user\UserInterface::getDisplayName() instead.
*/
public function getUsername();
/**
* Returns the unaltered login name of this account.
*
* @return string
* An unsanitized plain-text string with the name of this account that is
* used to log in. Only display this name to admins and to the user who owns
* this account, and only in the context of the name used to login. For
* any other display purposes, use
* \Drupal\Core\Session\AccountInterface::getDisplayName() instead.
*/
public function getAccountName();
/**
* Returns the display name of this account.
*
* By default, the passed-in object's 'name' property is used if it exists, or
* else, the site-defined value for the 'anonymous' variable. However, a module
* may override this by implementing
* else, the site-defined value for the 'anonymous' variable. However, a
* module may override this by implementing
* hook_user_format_name_alter(&$name, $account).
*
* @see hook_user_format_name_alter()
*
* @return
* An unsanitized string with the username to display.
* @return string|\Drupal\Component\Utility\SafeStringInterface
* Either a string that will be auto-escaped on output or a
* SafeStringInterface object that is already HTML escaped. Either is safe
* to be printed within HTML fragments.
*/
public function getUsername();
public function getDisplayName();
/**
* Returns the email address of this account.
......
......@@ -119,7 +119,21 @@ public function getPreferredAdminLangcode($fallback_to_default = TRUE) {
* {@inheritdoc}
*/
public function getUsername() {
return $this->getAccount()->getUsername();
return $this->getAccountName();
}
/**
* {@inheritdoc}
*/
public function getAccountName() {
return $this->getAccount()->getAccountName();
}
/**
* {@inheritdoc}
*/
public function getDisplayName() {
return $this->getAccount()->getDisplayName();
}
/**
......
......@@ -42,7 +42,7 @@ class UserSession implements AccountInterface {
*
* @var string
*/
public $name;
public $name = '';
/**
* The preferred language code of the account.
......@@ -160,6 +160,20 @@ function getPreferredAdminLangcode($fallback_to_default = TRUE) {
* {@inheritdoc}
*/
public function getUsername() {
return $this->getAccountName();
}
/**
* {@inheritdoc}
*/
public function getAccountName() {
return $this->name;
}
/**
* {@inheritdoc}
*/
public function getDisplayName() {
$name = $this->name ?: \Drupal::config('user.settings')->get('anonymous');
\Drupal::moduleHandler()->alter('user_format_name', $name, $this);
return $name;
......
......@@ -185,7 +185,7 @@ public function buildConfigurationForm(array $form, FormStateInterface $form_sta
'#default_value' => $this->configuration['message'],
'#cols' => '80',
'#rows' => '20',
'#description' => t('The message that should be sent. You may include placeholders like [node:title], [user:name], and [comment:body] to represent data that will be different each time message is sent. Not all placeholders will be available in all contexts.'),
'#description' => t('The message that should be sent. You may include placeholders like [node:title], [user:account-name], [user:display-name] and [comment:body] to represent data that will be different each time message is sent. Not all placeholders will be available in all contexts.'),
);
return $form;
}
......
......@@ -78,7 +78,7 @@ public function buildConfigurationForm(array $form, FormStateInterface $form_sta
'#default_value' => $this->configuration['message'],
'#required' => TRUE,
'#rows' => '8',
'#description' => t('The message to be displayed to the current user. You may include placeholders like [node:title], [user:name], and [comment:body] to represent data that will be different each time message is sent. Not all placeholders will be available in all contexts.'),
'#description' => t('The message to be displayed to the current user. You may include placeholders like [node:title], [user:account-name], [user:display-name] and [comment:body] to represent data that will be different each time message is sent. Not all placeholders will be available in all contexts.'),
);
return $form;
}
......
......@@ -54,7 +54,7 @@ function testCommentPreview() {
\Drupal::state()->set('user_hooks_test_user_format_name_alter_safe', TRUE);
$this->drupalPostForm('node/' . $this->node->id(), $edit, t('Preview'));
$this->assertTrue(SafeMarkup::isSafe($this->webUser->getUsername()), 'Username is marked safe');
$this->assertTrue(SafeMarkup::isSafe($this->webUser->getDisplayName()), 'Username is marked safe');
$this->assertNoEscaped('<em>' . $this->webUser->id() . '</em>');
$this->assertRaw('<em>' . $this->webUser->id() . '</em>');
......
......@@ -126,7 +126,7 @@ function contact_mail($key, &$message, $params) {
'!subject' => $contact_message->getSubject(),
'!form' => !empty($params['contact_form']) ? $params['contact_form']->label() : NULL,
'!form-url' => \Drupal::url('<current>', [], ['absolute' => TRUE, 'language' => $language]),
'!sender-name' => user_format_name($sender),
'!sender-name' => $sender->getDisplayName(),
);
if ($sender->isAuthenticated()) {
$variables['!sender-url'] = $sender->url('canonical', array('absolute' => TRUE, 'language' => $language));
......@@ -154,7 +154,7 @@ function contact_mail($key, &$message, $params) {
case 'user_mail':
case 'user_copy':
$variables += array(
'!recipient-name' => user_format_name($params['recipient']),
'!recipient-name' => $params['recipient']->getDisplayName(),
'!recipient-edit-url' => $params['recipient']->url('edit-form', array('absolute' => TRUE, 'language' => $language)),
);
$message['subject'] .= t('[!site-name] !subject', $variables, $options);
......
......@@ -117,7 +117,7 @@ public function contactPersonalPage(UserInterface $user) {
));
$form = $this->entityFormBuilder()->getForm($message);
$form['#title'] = $this->t('Contact @username', array('@username' => $user->getUsername()));
$form['#title'] = $this->t('Contact @username', array('@username' => $user->getDisplayName()));
$form['#cache']['contexts'][] = 'user.permissions';
return $form;
}
......
......@@ -56,7 +56,7 @@ function testFileTokenReplacement() {
$tests['[file:created:short]'] = format_date($file->getCreatedTime(), 'short', '', NULL, $language_interface->getId());
$tests['[file:changed]'] = format_date($file->getChangedTime(), 'medium', '', NULL, $language_interface->getId());
$tests['[file:changed:short]'] = format_date($file->getChangedTime(), 'short', '', NULL, $language_interface->getId());
$tests['[file:owner]'] = Html::escape(user_format_name($this->adminUser));
$tests['[file:owner]'] = Html::escape($this->adminUser->getDisplayName());
$tests['[file:owner:uid]'] = $file->getOwnerId();
$base_bubbleable_metadata = BubbleableMetadata::createFromObject($file);
......
......@@ -456,7 +456,7 @@ function template_preprocess_forums(&$variables) {
}
$forum_submitted = array('#theme' => 'forum_submitted', '#topic' => (object) array(
'uid' => $topic->getOwnerId(),
'name' => $topic->getOwner()->getUsername(),
'name' => $topic->getOwner()->getDisplayName(),
'created' => $topic->getCreatedTime(),
));
$variables['topics'][$id]->submitted = drupal_render($forum_submitted);
......
......@@ -121,7 +121,7 @@ public function render($row) {
),
array(
'key' => 'dc:creator',
'value' => $node->getOwner()->getUsername(),
'value' => $node->getOwner()->getDisplayName(),
),
array(
'key' => 'guid',
......
......@@ -378,7 +378,7 @@ function rdf_preprocess_user(&$variables) {
'#attributes' => array(
'about' => $account->url(),
'property' => $name_mapping['properties'],
'content' => $account->getUsername(),
'content' => $account->getDisplayName(),
'lang' => '',
),
);
......
......@@ -207,7 +207,7 @@ public function submitForm(array &$form, FormStateInterface $form_state) {
/* @var \Drupal\shortcut\Entity\ShortcutSet $set */
$set = $this->shortcutSetStorage->load($form_state->getValue('set'));
$replacements = array(
'%user' => $this->user->label(),
'%user' => $this->user->getDisplayName(),
'%set_name' => $set->label(),
);
drupal_set_message($account_is_user ? $this->t('You are now using the %set_name shortcut set.', $replacements) : $this->t('%user is now using the %set_name shortcut set.', $replacements));
......
cancel_confirm:
body: "[user:name],\n\nA request to cancel your account has been made at [site:name].\n\nYou may now cancel your account on [site:url-brief] by clicking this link or copying and pasting it into your browser:\n\n[user:cancel-url]\n\nNOTE: The cancellation of your account is not reversible.\n\nThis link expires in one day and nothing will happen if it is not used.\n\n-- [site:name] team"
subject: 'Account cancellation request for [user:name] at [site:name]'
body: "[user:display-name],\n\nA request to cancel your account has been made at [site:name].\n\nYou may now cancel your account on [site:url-brief] by clicking this link or copying and pasting it into your browser:\n\n[user:cancel-url]\n\nNOTE: The cancellation of your account is not reversible.\n\nThis link expires in one day and nothing will happen if it is not used.\n\n-- [site:name] team"
subject: 'Account cancellation request for [user:display-name] at [site:name]'
password_reset:
body: "[user:name],\n\nA request to reset the password for your account has been made at [site:name].\n\nYou may now log in by clicking this link or copying and pasting it to your browser:\n\n[user:one-time-login-url]\n\nThis link can only be used once to log in and will lead you to a page where you can set your password. It expires after one day and nothing will happen if it's not used.\n\n-- [site:name] team"
subject: 'Replacement login information for [user:name] at [site:name]'
body: "[user:display-name],\n\nA request to reset the password for your account has been made at [site:name].\n\nYou may now log in by clicking this link or copying and pasting it to your browser:\n\n[user:one-time-login-url]\n\nThis link can only be used once to log in and will lead you to a page where you can set your password. It expires after one day and nothing will happen if it's not used.\n\n-- [site:name] team"
subject: 'Replacement login information for [user:display-name] at [site:name]'
register_admin_created:
body: "[user:name],\n\nA site administrator at [site:name] has created an account for you. You may now log in by clicking this link or copying and pasting it to your browser:\n\n[user:one-time-login-url]\n\nThis link can only be used once to log in and will lead you to a page where you can set your password.\n\nAfter setting your password, you will be able to log in at [site:login-url] in the future using:\n\nusername: [user:name]\npassword: Your password\n\n-- [site:name] team"
body: "[user:display-name],\n\nA site administrator at [site:name] has created an account for you. You may now log in by clicking this link or copying and pasting it to your browser:\n\n[user:one-time-login-url]\n\nThis link can only be used once to log in and will lead you to a page where you can set your password.\n\nAfter setting your password, you will be able to log in at [site:login-url] in the future using:\n\nusername: [user:name]\npassword: Your password\n\n-- [site:name] team"
subject: 'An administrator created an account for you at [site:name]'
register_no_approval_required:
body: "[user:name],\n\nThank you for registering at [site:name]. You may now log in by clicking this link or copying and pasting it to your browser:\n\n[user:one-time-login-url]\n\nThis link can only be used once to log in and will lead you to a page where you can set your password.\n\nAfter setting your password, you will be able to log in at [site:login-url] in the future using:\n\nusername: [user:name]\npassword: Your password\n\n-- [site:name] team"
subject: 'Account details for [user:name] at [site:name]'
body: "[user:display-name],\n\nThank you for registering at [site:name]. You may now log in by clicking this link or copying and pasting it to your browser:\n\n[user:one-time-login-url]\n\nThis link can only be used once to log in and will lead you to a page where you can set your password.\n\nAfter setting your password, you will be able to log in at [site:login-url] in the future using:\n\nusername: [user:name]\npassword: Your password\n\n-- [site:name] team"
subject: 'Account details for [user:display-name] at [site:name]'
register_pending_approval:
body: "[user:name],\n\nThank you for registering at [site:name]. Your application for an account is currently pending approval. Once it has been approved, you will receive another email containing information about how to log in, set your password, and other details.\n\n\n-- [site:name] team"
subject: 'Account details for [user:name] at [site:name] (pending admin approval)'
body: "[user:display-name],\n\nThank you for registering at [site:name]. Your application for an account is currently pending approval. Once it has been approved, you will receive another email containing information about how to log in, set your password, and other details.\n\n\n-- [site:name] team"
subject: 'Account details for [user:display-name] at [site:name] (pending admin approval)'
register_pending_approval_admin:
body: "[user:name] has applied for an account.\n\n[user:edit-url]"
subject: 'Account details for [user:name] at [site:name] (pending admin approval)'
body: "[user:display-name] has applied for an account.\n\n[user:edit-url]"
subject: 'Account details for [user:display-name] at [site:name] (pending admin approval)'
status_activated:
body: "[user:name],\n\nYour account at [site:name] has been activated.\n\nYou may now log in by clicking this link or copying and pasting it into your browser:\n\n[user:one-time-login-url]\n\nThis link can only be used once to log in and will lead you to a page where you can set your password.\n\nAfter setting your password, you will be able to log in at [site:login-url] in the future using:\n\nusername: [user:name]\npassword: Your password\n\n-- [site:name] team"
subject: 'Account details for [user:name] at [site:name] (approved)'
body: "[user:display-name],\n\nYour account at [site:name] has been activated.\n\nYou may now log in by clicking this link or copying and pasting it into your browser:\n\n[user:one-time-login-url]\n\nThis link can only be used once to log in and will lead you to a page where you can set your password.\n\nAfter setting your password, you will be able to log in at [site:login-url] in the future using:\n\nusername: [user:account-name]\npassword: Your password\n\n-- [site:name] team"
subject: 'Account details for [user:display-name] at [site:name] (approved)'
status_blocked:
body: "[user:name],\n\nYour account on [site:name] has been blocked.\n\n-- [site:name] team"
subject: 'Account details for [user:name] at [site:name] (blocked)'
body: "[user:display-name],\n\nYour account on [site:account-name] has been blocked.\n\n-- [site:name] team"
subject: 'Account details for [user:display-name] at [site:name] (blocked)'
status_canceled:
body: "[user:name],\n\nYour account on [site:name] has been canceled.\n\n-- [site:name] team"
subject: 'Account details for [user:name] at [site:name] (canceled)'
body: "[user:display-name],\n\nYour account on [site:name] has been canceled.\n\n-- [site:name] team"
subject: 'Account details for [user:display-name] at [site:name] (canceled)'
langcode: en
......@@ -201,7 +201,7 @@ public function buildForm(array $form, FormStateInterface $form_state) {
);
// These email tokens are shared for all settings, so just define
// the list once to help ensure they stay in sync.
$email_token_help = $this->t('Available variables are: [site:name], [site:url], [user:name], [user:mail], [site:login-url], [site:url-brief], [user:edit-url], [user:one-time-login-url], [user:cancel-url].');
$email_token_help = $this->t('Available variables are: [site:name], [site:url], [user:display-name], [user:account-name], [user:mail], [site:login-url], [site:url-brief], [user:edit-url], [user:one-time-login-url], [user:cancel-url].');
$form['email_admin_created'] = array(
'#type' => 'details',
......
......@@ -362,7 +362,21 @@ public function isAnonymous() {
* {@inheritdoc}
*/
public function getUsername() {
$name = $this->get('name')->value ?: \Drupal::config('user.settings')->get('anonymous');
return $this->getAccountName();
}
/**
* {@inheritdoc}
*/
public function getAccountName() {
return $this->get('name')->value ?: '';
}
/**
* {@inheritdoc}
*/
public function getDisplayName() {
$name = $this->getAccountName() ?: \Drupal::config('user.settings')->get('anonymous');
\Drupal::moduleHandler()->alter('user_format_name', $name, $this);
return $name;
}
......@@ -411,7 +425,10 @@ public static function getAnonymousUser() {
$entity_type = $entity_manager->getDefinition('user');
$class = $entity_type->getClass();
static::$anonymousUser = new $class(['uid' => [LanguageInterface::LANGCODE_DEFAULT => 0]], $entity_type->id());
static::$anonymousUser = new $class([
'uid' => [LanguageInterface::LANGCODE_DEFAULT => 0],
'name' => [LanguageInterface::LANGCODE_DEFAULT => ''],
], $entity_type->id());
}
return clone static::$anonymousUser;
}
......
......@@ -202,7 +202,7 @@ public function entityQueryAlter(SelectInterface $query) {
$value_part->condition('anonymous_name', $condition['value'], $condition['operator']);
$value_part->compile($this->connection, $query);
$or->condition(db_and()
->where(str_replace('anonymous_name', ':anonymous_name', (string) $value_part), $value_part->arguments() + array(':anonymous_name' => user_format_name($this->userStorage->load(0))))
->where(str_replace('anonymous_name', ':anonymous_name', (string) $value_part), $value_part->arguments() + array(':anonymous_name' => \Drupal::config('user.settings')->get('anonymous')))
->condition('base_table.uid', 0)
);
$query->condition($or);
......
......@@ -72,7 +72,7 @@ public function viewElements(FieldItemListInterface $items) {
}
else {
$elements[$delta] = [
'#markup' => $user->getUsername(),
'#markup' => $user->getDisplayName(),
'#cache' => [
'tags' => $user->getCacheTags(),
],
......
......@@ -148,7 +148,7 @@ public function execute() {
foreach ($accounts as $account) {
$result = array(
'title' => $account->getUsername(),
'title' => $account->getDisplayName(),
'link' => $account->url('canonical', array('absolute' => TRUE)),
);
if ($this->currentUser->hasPermission('administer users')) {
......
......@@ -87,7 +87,17 @@ public function testFormatter() {
$this->assertEqual(spl_object_hash($user), spl_object_hash($result[0]['#account']));
$result = $user->{$this->fieldName}->view(['type' => 'user_name', 'settings' => ['link_to_entity' => FALSE]]);
$this->assertEqual($user->getUsername(), $result[0]['#markup']);
$this->assertEqual($user->getDisplayName(), $result[0]['#markup']);
$user = User::getAnonymousUser();
$result = $user->{$this->fieldName}->view(['type' => 'user_name']);
$this->assertEqual('username', $result[0]['#theme']);
$this->assertEqual(spl_object_hash($user), spl_object_hash($result[0]['#account']));
$result = $user->{$this->fieldName}->view(['type' => 'user_name', 'settings' => ['link_to_entity' => FALSE]]);
$this->assertEqual($user->getDisplayName(), $result[0]['#markup']);
$this->assertEqual($this->config('user.settings')->get('anonymous'), $result[0]['#markup']);
}
}
......@@ -367,7 +367,7 @@ function testUserAnonymize() {
$storage->resetCache(array($comment->id()));
$test_comment = $storage->load($comment->id());
$this->assertTrue(($test_comment->getOwnerId() == 0 && $test_comment->isPublished()), 'Comment of the user has been attributed to anonymous user.');
$this->assertEqual($test_comment->getAuthorName(), $anonymous_user->getUsername(), 'Comment of the user has been attributed to anonymous user name.');
$this->assertEqual($test_comment->getAuthorName(), $anonymous_user->getDisplayName(), 'Comment of the user has been attributed to anonymous user name.');
// Confirm that the confirmation message made it through to the end user.
$this->assertRaw(t('%name has been deleted.', array('%name' => $account->getUsername())), "Confirmation message displayed to user.");
......
......@@ -16,6 +16,13 @@
*/
class UserEditedOwnAccountTest extends WebTestBase {
/**
* Modules to enable.
*
* @var array
*/
public static $modules = array('user_form_test');
function testUserEditedOwnAccount() {
// Change account setting 'Who can register accounts?' to Administrators
// only.
......
......@@ -22,7 +22,7 @@ class UserEntityCallbacksTest extends WebTestBase {
*
* @var array
*/
public static $modules = array('user');
public static $modules = array('user', 'user_hooks_test');
/**
* An authenticated user to use for testing.
......@@ -55,6 +55,14 @@ function testLabelCallback() {
$name = $this->randomMachineName();
$this->config('user.settings')->set('anonymous', $name)->save();
$this->assertEqual($this->anonymous->label(), $name, 'The variable anonymous should be used for name of uid 0');
$this->assertEqual($this->anonymous->getDisplayName(), $name, 'The variable anonymous should be used for display name of uid 0');
$this->assertEqual($this->anonymous->getUserName(), '', 'The raw anonymous user name should be empty string');
// Set to test the altered username.
\Drupal::state()->set('user_hooks_test_user_format_name_alter', TRUE);
$this->assertEqual($this->account->getDisplayName(), '<em>' . $this->account->id() . '</em>', 'The user display name should be altered.');
$this->assertEqual($this->account->getUsername(), $this->account->name->value, 'The user name should not be altered.');
}
}
......@@ -26,8 +26,11 @@ class UserTokenReplaceTest extends WebTestBase {
*
* @var array
*/
public static $modules = array('language');
public static $modules = array('language', 'user_hooks_test');
/**
* {@inheritdoc}
*/
protected function setUp() {
parent::setUp();
ConfigurableLanguage::createFromLangcode('de')->save();
......@@ -44,6 +47,8 @@ function testUserTokenReplacement() {
'language' => $language_interface,
);
\Drupal::state()->set('user_hooks_test_user_format_name_alter', TRUE);
// Create two users and log them in one after another.
$user1 = $this->drupalCreateUser(array());
$user2 = $this->drupalCreateUser(array());
......@@ -57,7 +62,9 @@ function testUserTokenReplacement() {
// Generate and test sanitized tokens.
$tests = array();
$tests['[user:uid]'] = $account->id();
$tests['[user:name]'] = Html::escape(user_format_name($account));
$tests['[user:name]'] = Html::escape($account->getAccountName());
$tests['[user:account-name]'] = Html::escape($account->getAccountName());
$tests['[user:display-name]'] = $account->getDisplayName();
$tests['[user:mail]'] = Html::escape($account->getEmail());
$tests['[user:url]'] = $account->url('canonical', $url_options);
$tests['[user:edit-url]'] = $account->url('edit-form', $url_options);
......@@ -65,12 +72,16 @@ function testUserTokenReplacement() {
$tests['[user:last-login:short]'] = format_date($account->getLastLoginTime(), 'short', '', NULL, $language_interface->getId());
$tests['[user:created]'] = format_date($account->getCreatedTime(), 'medium', '', NULL, $language_interface->getId());
$tests['[user:created:short]'] = format_date($account->getCreatedTime(), 'short', '', NULL, $language_interface->getId());
$tests['[current-user:name]'] = Html::escape(user_format_name($global_account));
$tests['[current-user:name]'] = Html::escape($global_account->getAccountName());
$tests['[current-user:account-name]'] = Html::escape($global_account->getAccountName());
$tests['[current-user:display-name]'] = $global_account->getDisplayName();
$base_bubbleable_metadata = BubbleableMetadata::createFromObject($account);
$metadata_tests = [];
$metadata_tests['[user:uid]'] = $base_bubbleable_metadata;
$metadata_tests['[user:name]'] = $base_bubbleable_metadata;
$metadata_tests['[user:account-name]'] = $base_bubbleable_metadata;
$metadata_tests['[user:display-name]'] = $base_bubbleable_metadata;
$metadata_tests['[user:mail]'] = $base_bubbleable_metadata;
$metadata_tests['[user:url]'] = $base_bubbleable_metadata;
$metadata_tests['[user:edit-url]'] = $base_bubbleable_metadata;
......@@ -86,6 +97,8 @@ function testUserTokenReplacement() {
$metadata_tests['[user:created]'] = $bubbleable_metadata;
$metadata_tests['[user:created:short]'] = $bubbleable_metadata;
$metadata_tests['[current-user:name]'] = $base_bubbleable_metadata->merge(BubbleableMetadata::createFromObject($global_account)->addCacheContexts(['user']));
$metadata_tests['[current-user:account-name]'] = $base_bubbleable_metadata->merge(BubbleableMetadata::createFromObject($global_account)->addCacheContexts(['user']));
$metadata_tests['[current-user:display-name]'] = $base_bubbleable_metadata->merge(BubbleableMetadata::createFromObject($global_account)->addCacheContexts(['user']));
// Test to make sure that we generated something for each token.
$this->assertFalse(in_array(0, array_map('strlen', $tests)), 'No empty tokens generated.');
......@@ -101,14 +114,14 @@ function testUserTokenReplacement() {
$anonymous_user = User::load(0);
$tests = [];
$tests['[user:uid]'] = t('not yet assigned');
$tests['[user:name]'] = Html::escape(user_format_name($anonymous_user));
$tests['[user:display-name]'] = $anonymous_user->getDisplayName();
$base_bubbleable_metadata = BubbleableMetadata::createFromObject($anonymous_user);
$metadata_tests = [];
$metadata_tests['[user:uid]'] = $base_bubbleable_metadata;
$bubbleable_metadata = clone $base_bubbleable_metadata;
$bubbleable_metadata->addCacheableDependency(\Drupal::config('user.settings'));
$metadata_tests['[user:name]'] = $bubbleable_metadata;
$metadata_tests['[user:display-name]'] = $bubbleable_metadata;
foreach ($tests as $input => $expected) {
$bubbleable_metadata = new BubbleableMetadata();
......@@ -119,9 +132,13 @@ function testUserTokenReplacement() {
// Generate and test unsanitized tokens.
$tests = [];
$tests['[user:name]'] = user_format_name($account);
$tests['[user:name]'] = $account->getAccountName();
$tests['[user:account-name]'] = $account->getAccountName();
$tests['[user:display-name]'] = $account->getDisplayName();
$tests['[user:mail]'] = $account->getEmail();
$tests['[current-user:name]'] = user_format_name($global_account);
$tests['[current-user:account-name]'] = $global_account->getAccountname();
$tests['[current-user:name]'] = $global_account->getAccountName();
$tests['[current-user:display-name]'] = $global_account->getDisplayName();
foreach ($tests as $input => $expected) {
$output = $token_service->replace($input, array('user' => $account), array('langcode' => $language_interface->getId(), 'sanitize' => FALSE));
......
......@@ -29,7 +29,8 @@ public function testUserName() {
/** @var \Drupal\Core\Render\RendererInterface $renderer */
$renderer = \Drupal::service('renderer');
$this->drupalLogin($this->drupalCreateUser(array('access user profiles')));
$new_user = $this->drupalCreateUser(array('access user profiles'));
$this->drupalLogin($new_user);
// Set defaults.
$view = Views::getView('test_views_handler_field_user_name');
......@@ -48,24 +49,18 @@ public function testUserName() {
});
$this->assertTrue(strpos($render, $anon_name) !== FALSE, 'For user 0 it should use the default anonymous name by default.');
$username = $this->randomMachineName();
$view->result[0]->_entity->setUsername($username);
$view->result[0]->_entity->uid->value = 1;
$render = $renderer->executeInRenderContext(new RenderContext(), function () use ($view) {
return $view->field['name']->advancedRender($view->result[0]);
$render = $renderer->executeInRenderContext(new RenderContext(), function () use ($view, $new_user) {
return $view->field['name']->advancedRender($view->result[$new_user->id()]);
});
$this->assertTrue(strpos($render, $username) !== FALSE, 'If link to user is checked the username should be part of the output.');
$this->assertTrue(strpos($render, 'user/1') !== FALSE, 'If link to user is checked the link to the user should appear as well.');
$this->assertTrue(strpos($render, $new_user->getDisplayName()) !== FALSE, 'If link to user is checked the username should be part of the output.');
$this->assertTrue(strpos($render, 'user/' . $new_user->id()) !== FALSE, 'If link to user is checked the link to the user should appear as well.');
$view->field['name']->options['link_to_user'] = FALSE;
$view->field['name']->options['type'] = 'string';
$username = $this->randomMachineName();
$view->result[0]->_entity->setUsername($username);
$view->result[0]->_entity->uid->value = 1;
$render = $renderer->executeInRenderContext(new RenderContext(), function () use ($view) {
return $view->field['name']->advancedRender($view->result[0]);
$render = $renderer->executeInRenderContext(new RenderContext(), function () use ($view, $new_user) {
return $view->field['name']->advancedRender($view->result[$new_user->id()]);
});
$this->assertEqual($render, $username, 'If the user is not linked the username should be printed out for a normal user.');
$this->assertEqual($render, $new_user->getDisplayName(), 'If the user is not linked the username should be printed out for a normal user.');
}
......
......@@ -51,6 +51,12 @@ display:
type: default
row:
type: fields
sorts:
uid:
id: uid
table: users
field: uid
plugin_id: standard
display_plugin: default
display_title: Master
id: default
......
......@@ -107,17 +107,17 @@ function hook_user_cancel_methods_alter(&$methods) {
/**
* Alter the username that is displayed for a user.
*
* Called by user_format_name() to allow modules to alter the username that's
* displayed. Can be used to ensure user privacy in situations where
* 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->name is too revealing.
*
* @param string $name
* The string that user_format_name() will return.
* The string that $account->getDisplayName() will return.
*
* @param object $account
* @param $account
* The account object passed to user_format_name().
*
* @see user_format_name()
* @see $account->getDisplayName()
*/
function hook_user_format_name_alter(&$name, $account) {
// Display the user's uid instead of name.
......
......@@ -416,12 +416,12 @@ function user_preprocess_block(&$variables) {
* An unsanitized string with the username to display.
*
* @deprecated in Drupal 8.0.x-dev, will be removed before Drupal 9.0.0.
* Use \Drupal\Core\Session\AccountInterface::getUsername().
* Use \Drupal\Core\Session\AccountInterface::getDisplayName().
*
* @todo Remove usage in https://www.drupal.org/node/2311219.
*/
function user_format_name(AccountInterface $account) {
return $account->getUsername();
return $account->getDisplayName();
}
/**
......@@ -469,7 +469,8 @@ function template_preprocess_username(&$variables) {
// unsanitized version, in case other preprocess functions want to implement
// their own shortening logic or add markup. If they do so, they must ensure
// that $variables['name'] is safe for printing.
$name = $variables['name_raw'] = $account->getUsername();
$name = $account->getDisplayName();
$variables['name_raw'] = $account->getUsername();
if (Unicode::strlen($name) > 20) {
$name = Unicode::truncate($name, 15, FALSE, TRUE);
$variables['truncated'] = TRUE;
......@@ -738,8 +739,8 @@ function _user_cancel($edit, $account, $method) {
}
$account->block();
$account->save();
drupal_set_message(t('%name has been disabled.', array('%name' => $account->getUsername())));
$logger->notice('Blocked user: %name %email.', array('%name' => $account->getUsername(), '%email' => '<' . $account->getEmail() . '>'));
drupal_set_message(t('%name has been disabled.', array('%name' => $account->getDisplayName())));
$logger->notice('Blocked user: %name %email.', array('%name' => $account->getAccountName(), '%email' => '<' . $account->getEmail() . '>'));
break;
case 'user_cancel_reassign':
......@@ -749,8 +750,8 @@ function _user_cancel($edit, $account, $method) {
_user_mail_notify('status_canceled', $account);
}
$account->delete();
drupal_set_message(t('%name has been deleted.', array('%name' => $account->getUsername())));
$logger->notice('Deleted user: %name %email.', array('%name' => $account->getUsername(), '%email' => '<' . $account->getEmail() . '>'));
drupal_set_message(t('%name has been deleted.', array('%name' => $account->getDisplayName())));
$logger->notice('Deleted user: %name %email.', array('%name' => $account->getAccountName(), '%email' => '<' . $account->getEmail() . '>'));
break;
}
......@@ -1362,7 +1363,7 @@ function user_toolbar() {