Newer
Older
<?php
/**
* @file
* Contains \Drupal\user\Entity\User.
*/
namespace Drupal\user\Entity;
use Drupal\Core\Entity\ContentEntityBase;
use Drupal\Core\Entity\EntityMalformedException;
use Drupal\Core\Entity\EntityStorageInterface;
use Drupal\Core\Entity\EntityTypeInterface;
Alex Pott
committed
use Drupal\Core\Field\BaseFieldDefinition;
Alex Pott
committed
use Drupal\Core\Language\LanguageInterface;
use Drupal\user\RoleInterface;
use Drupal\user\UserInterface;
/**
* Defines the user entity class.
Angie Byron
committed
*
* The base table name here is plural, despite Drupal table naming standards,
* because "user" is a reserved word in many databases.
*
Alex Pott
committed
* @ContentEntityType(
Angie Byron
committed
* id = "user",
* label = @Translation("User"),
Alex Pott
committed
* handlers = {
catch
committed
* "storage" = "Drupal\user\UserStorage",
* "storage_schema" = "Drupal\user\UserStorageSchema",
* "access" = "Drupal\user\UserAccessControlHandler",
* "list_builder" = "Drupal\user\UserListBuilder",
* "views_data" = "Drupal\user\UserViewsData",
* "route_provider" = {
* "html" = "Drupal\user\Entity\UserRouteProvider",
* },
Alex Pott
committed
* "default" = "Drupal\user\ProfileForm",
* "cancel" = "Drupal\user\Form\UserCancelForm",
Alex Pott
committed
* "register" = "Drupal\user\RegisterForm"
* "translation" = "Drupal\user\ProfileTranslationHandler"
Angie Byron
committed
* },
* admin_permission = "administer users",
Angie Byron
committed
* base_table = "users",
Alex Pott
committed
* data_table = "users_field_data",
catch
committed
* label_callback = "user_format_name",
Angie Byron
committed
* translatable = TRUE,
Angie Byron
committed
* entity_keys = {
* "id" = "uid",
* "langcode" = "langcode",
Angie Byron
committed
* "uuid" = "uuid"
Alex Pott
committed
* },
* links = {
* "canonical" = "/user/{user}",
* "edit-form" = "/user/{user}/edit",
* "cancel-form" = "/user/{user}/cancel",
Alex Pott
committed
* "collection" = "/admin/people",
Alex Pott
committed
* },
Angie Byron
committed
* field_ui_base_route = "entity.user.admin_form",
* common_reference_target = TRUE
Angie Byron
committed
* )
*/
class User extends ContentEntityBase implements UserInterface {
/**
* The hostname for this user.
*
* @var string
*/
protected $hostname;
Alex Pott
committed
/**
* {@inheritdoc}
*/
public function isNew() {
return !empty($this->enforceIsNew) || $this->id() === NULL;
}
/**
* {@inheritdoc}
*/
catch
committed
public function preSave(EntityStorageInterface $storage) {
parent::preSave($storage);
Angie Byron
committed
Dries Buytaert
committed
// Make sure that the authenticated/anonymous roles are not persisted.
foreach ($this->get('roles') as $index => $item) {
if (in_array($item->target_id, array(RoleInterface::ANONYMOUS_ID, RoleInterface::AUTHENTICATED_ID))) {
Dries Buytaert
committed
$this->get('roles')->offsetUnset($index);
}
}
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
// Update the user password if it has changed.
if ($this->isNew() || ($this->pass->value && $this->pass->value != $this->original->pass->value)) {
// Allow alternate password hashing schemes.
$this->pass->value = \Drupal::service('password')->hash(trim($this->pass->value));
// Abort if the hashing failed and returned FALSE.
if (!$this->pass->value) {
throw new EntityMalformedException('The entity does not have a password.');
}
}
if (!$this->isNew()) {
// If the password is empty, that means it was not changed, so use the
// original password.
if (empty($this->pass->value)) {
$this->pass->value = $this->original->pass->value;
}
}
// Store account cancellation information.
foreach (array('user_cancel_method', 'user_cancel_notify') as $key) {
if (isset($this->{$key})) {
\Drupal::service('user.data')->set('user', $this->id(), substr($key, 5), $this->{$key});
}
}
}
/**
* {@inheritdoc}
*/
catch
committed
public function postSave(EntityStorageInterface $storage, $update = TRUE) {
parent::postSave($storage, $update);
Angie Byron
committed
if ($update) {
$session_manager = \Drupal::service('session_manager');
// If the password has been changed, delete all open sessions for the
// user and recreate the current one.
if ($this->pass->value != $this->original->pass->value) {
$session_manager->delete($this->id());
if ($this->id() == \Drupal::currentUser()->id()) {
Alex Pott
committed
\Drupal::service('session')->migrate();
}
}
// If the user was blocked, delete the user's sessions to force a logout.
if ($this->original->status->value != $this->status->value && $this->status->value == 0) {
$session_manager->delete($this->id());
}
// Send emails after we have the new user object.
if ($this->status->value != $this->original->status->value) {
// The user's status is changing; conditionally send notification email.
$op = $this->status->value == 1 ? 'status_activated' : 'status_blocked';
Alex Pott
committed
_user_mail_notify($op, $this);
}
}
}
/**
* {@inheritdoc}
*/
catch
committed
public static function postDelete(EntityStorageInterface $storage, array $entities) {
parent::postDelete($storage, $entities);
Angie Byron
committed
$uids = array_keys($entities);
\Drupal::service('user.data')->delete(NULL, $uids);
}
/**
* {@inheritdoc}
*/
public function getRoles($exclude_locked_roles = FALSE) {
$roles = array();
Dries Buytaert
committed
// Users with an ID always have the authenticated user role.
if (!$exclude_locked_roles) {
if ($this->isAuthenticated()) {
$roles[] = RoleInterface::AUTHENTICATED_ID;
Dries Buytaert
committed
}
else {
$roles[] = RoleInterface::ANONYMOUS_ID;
Dries Buytaert
committed
}
}
foreach ($this->get('roles') as $role) {
Dries Buytaert
committed
if ($role->target_id) {
$roles[] = $role->target_id;
return $roles;
}
/**
* {@inheritdoc}
*/
public function getSecureSessionId() {
return NULL;
}
/**
* {@inheritdoc}
*/
public function getSessionData() {
return array();
}
/**
* {@inheritdoc}
*/
public function getSessionId() {
return NULL;
}
/**
* {@inheritdoc}
*/
public function getHostname() {
if (!isset($this->hostname) && \Drupal::hasRequest()) {
$this->hostname = \Drupal::request()->getClientIp();
}
return $this->hostname;
}
/**
* {@inheritdoc}
*/
public function hasRole($rid) {
return in_array($rid, $this->getRoles());
}
/**
* {@inheritdoc}
*/
public function addRole($rid) {
Dries Buytaert
committed
if (in_array($rid, [RoleInterface::AUTHENTICATED_ID, RoleInterface::ANONYMOUS_ID])) {
Dries Buytaert
committed
throw new \InvalidArgumentException('Anonymous or authenticated role ID must not be assigned manually.');
}
$roles = $this->getRoles(TRUE);
$roles[] = $rid;
$this->set('roles', array_unique($roles));
}
/**
* {@inheritdoc}
*/
public function removeRole($rid) {
Dries Buytaert
committed
$this->set('roles', array_diff($this->getRoles(TRUE), array($rid)));
}
/**
* {@inheritdoc}
*/
public function hasPermission($permission) {
// User #1 has all privileges.
if ((int) $this->id() === 1) {
return TRUE;
}
return $this->getRoleStorage()->isPermissionInRoles($permission, $this->getRoles());
}
/**
* {@inheritdoc}
*/
public function getPassword() {
return $this->get('pass')->value;
}
/**
* {@inheritdoc}
*/
public function setPassword($password) {
$this->get('pass')->value = $password;
}
/**
* {@inheritdoc}
*/
public function getEmail() {
return $this->get('mail')->value;
}
/**
* {@inheritdoc}
*/
public function setEmail($mail) {
$this->get('mail')->value = $mail;
}
/**
* {@inheritdoc}
*/
public function getCreatedTime() {
return $this->get('created')->value;
}
/**
* {@inheritdoc}
*/
public function getLastAccessedTime() {
return $this->get('access')->value;
}
/**
* {@inheritdoc}
*/
public function setLastAccessTime($timestamp) {
$this->get('access')->value = $timestamp;
}
/**
* {@inheritdoc}
*/
public function getLastLoginTime() {
return $this->get('login')->value;
}
/**
* {@inheritdoc}
*/
public function setLastLoginTime($timestamp) {
$this->get('login')->value = $timestamp;
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
}
/**
* {@inheritdoc}
*/
public function isActive() {
return $this->get('status')->value == 1;
}
/**
* {@inheritdoc}
*/
public function isBlocked() {
return $this->get('status')->value == 0;
}
/**
* {@inheritdoc}
*/
public function activate() {
$this->get('status')->value = 1;
return $this;
}
/**
* {@inheritdoc}
*/
public function block() {
$this->get('status')->value = 0;
return $this;
}
/**
* {@inheritdoc}
*/
public function getTimeZone() {
return $this->get('timezone')->value;
}
/**
* {@inheritdoc}
*/
catch
committed
function getPreferredLangcode($fallback_to_default = TRUE) {
$language_list = $this->languageManager()->getLanguages();
$preferred_langcode = $this->get('preferred_langcode')->value;
if (!empty($preferred_langcode) && isset($language_list[$preferred_langcode])) {
return $language_list[$preferred_langcode]->getId();
}
else {
return $fallback_to_default ? $this->languageManager()->getDefaultLanguage()->getId() : '';
}
}
/**
* {@inheritdoc}
*/
catch
committed
function getPreferredAdminLangcode($fallback_to_default = TRUE) {
$language_list = $this->languageManager()->getLanguages();
$preferred_langcode = $this->get('preferred_admin_langcode')->value;
if (!empty($preferred_langcode) && isset($language_list[$preferred_langcode])) {
return $language_list[$preferred_langcode]->getId();
}
else {
return $fallback_to_default ? $this->languageManager()->getDefaultLanguage()->getId() : '';
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
}
}
/**
* {@inheritdoc}
*/
public function getInitialEmail() {
return $this->get('init')->value;
}
/**
* {@inheritdoc}
*/
public function isAuthenticated() {
return $this->id() > 0;
}
/**
* {@inheritdoc}
*/
public function isAnonymous() {
return $this->id() == 0;
}
/**
* {@inheritdoc}
*/
public function getUsername() {
$name = $this->get('name')->value ?: \Drupal::config('user.settings')->get('anonymous');
\Drupal::moduleHandler()->alter('user_format_name', $name, $this);
return $name;
}
/**
* {@inheritdoc}
*/
public function setUsername($username) {
$this->set('name', $username);
return $this;
}
/**
* {@inheritdoc}
*/
public function getChangedTime() {
return $this->get('changed')->value;
}
Alex Pott
committed
/**
* {@inheritdoc}
*/
public static function baseFieldDefinitions(EntityTypeInterface $entity_type) {
Alex Pott
committed
$fields['uid'] = BaseFieldDefinition::create('integer')
->setLabel(t('User ID'))
->setDescription(t('The user ID.'))
catch
committed
->setReadOnly(TRUE)
->setSetting('unsigned', TRUE);
Alex Pott
committed
$fields['uuid'] = BaseFieldDefinition::create('uuid')
->setLabel(t('UUID'))
->setDescription(t('The user UUID.'))
->setReadOnly(TRUE);
Alex Pott
committed
$fields['langcode'] = BaseFieldDefinition::create('language')
->setLabel(t('Language code'))
Alex Pott
committed
->setDescription(t('The user language code.'))
->setTranslatable(TRUE);
Alex Pott
committed
$fields['preferred_langcode'] = BaseFieldDefinition::create('language')
->setLabel(t('Preferred language code'))
Alex Pott
committed
->setDescription(t("The user's preferred language code for receiving emails and viewing the site."))
// @todo: Define this via an options provider once
// https://www.drupal.org/node/2329937 is completed.
->addPropertyConstraints('value', array(
'AllowedValues' => array('callback' => __CLASS__ . '::getAllowedConfigurableLanguageCodes'),
));
Alex Pott
committed
$fields['preferred_admin_langcode'] = BaseFieldDefinition::create('language')
->setLabel(t('Preferred admin language code'))
->setDescription(t("The user's preferred language code for viewing administration pages."))
Alex Pott
committed
// @todo: A default value of NULL is ignored, so we have to specify
// an empty field item structure instead. Fix this in
// https://www.drupal.org/node/2318605.
->setDefaultValue(array(0 => array ('value' => NULL)))
// @todo: Define this via an options provider once
// https://www.drupal.org/node/2329937 is completed.
->addPropertyConstraints('value', array(
'AllowedValues' => array('callback' => __CLASS__ . '::getAllowedConfigurableLanguageCodes'),
));
// The name should not vary per language. The username is the visual
// identifier for a user and needs to be consistent in all languages.
Alex Pott
committed
$fields['name'] = BaseFieldDefinition::create('string')
->setLabel(t('Name'))
->setDescription(t('The name of this user.'))
Alex Pott
committed
->setDefaultValue('')
->setConstraints(array(
// No Length constraint here because the UserName constraint also covers
catch
committed
// that.
'UserName' => array(),
'UserNameUnique' => array(),
));
Angie Byron
committed
$fields['pass'] = BaseFieldDefinition::create('password')
->setLabel(t('Password'))
->setDescription(t('The password of this user (hashed).'));
Alex Pott
committed
$fields['mail'] = BaseFieldDefinition::create('email')
->setLabel(t('Email'))
->setDescription(t('The email of this user.'))
Alex Pott
committed
->setDefaultValue('')
Alex Pott
committed
->addConstraint('UserMailUnique')
->addConstraint('UserMailRequired');
Alex Pott
committed
$fields['timezone'] = BaseFieldDefinition::create('string')
->setLabel(t('Timezone'))
->setDescription(t('The timezone of this user.'))
Alex Pott
committed
->setSetting('max_length', 32)
// @todo: Define this via an options provider once
// https://www.drupal.org/node/2329937 is completed.
->addPropertyConstraints('value', array(
'AllowedValues' => array('callback' => __CLASS__ . '::getAllowedTimezones'),
));
Alex Pott
committed
$fields['status'] = BaseFieldDefinition::create('boolean')
->setLabel(t('User status'))
->setDescription(t('Whether the user is active or blocked.'))
Alex Pott
committed
->setDefaultValue(FALSE);
Alex Pott
committed
$fields['created'] = BaseFieldDefinition::create('created')
->setLabel(t('Created'))
->setDescription(t('The time that the user was created.'));
$fields['changed'] = BaseFieldDefinition::create('changed')
->setLabel(t('Changed'))
->setDescription(t('The time that the user was last edited.'));
Alex Pott
committed
$fields['access'] = BaseFieldDefinition::create('timestamp')
->setLabel(t('Last access'))
->setDescription(t('The time that the user last accessed the site.'))
Alex Pott
committed
->setDefaultValue(0);
Alex Pott
committed
$fields['login'] = BaseFieldDefinition::create('timestamp')
->setLabel(t('Last login'))
->setDescription(t('The time that the user last logged in.'))
Alex Pott
committed
->setDefaultValue(0);
Alex Pott
committed
$fields['init'] = BaseFieldDefinition::create('email')
->setLabel(t('Initial email'))
->setDescription(t('The email address used for initial account creation.'))
Alex Pott
committed
->setDefaultValue('');
$fields['roles'] = BaseFieldDefinition::create('entity_reference')
->setLabel(t('Roles'))
Alex Pott
committed
->setCardinality(BaseFieldDefinition::CARDINALITY_UNLIMITED)
->setDescription(t('The roles the user has.'))
->setSetting('target_type', 'user_role');
return $fields;
Alex Pott
committed
}
/**
* Returns the role storage object.
*
* @return \Drupal\user\RoleStorageInterface
* The role storage object.
*/
protected function getRoleStorage() {
return \Drupal::entityManager()->getStorage('user_role');
}
Alex Pott
committed
/**
* Defines allowed timezones for the field's AllowedValues constraint.
*
* @return string[]
* The allowed values.
*/
public static function getAllowedTimezones() {
return array_keys(system_time_zones());
}
/**
* Defines allowed configurable language codes for AllowedValues constraints.
*
* @return string[]
* The allowed values.
*/
public static function getAllowedConfigurableLanguageCodes() {
return array_keys(\Drupal::languageManager()->getLanguages(LanguageInterface::STATE_CONFIGURABLE));
}