You are here

class AccountProxy in Drupal 9

Same name and namespace in other branches
  1. 8 core/lib/Drupal/Core/Session/AccountProxy.php \Drupal\Core\Session\AccountProxy

A proxied implementation of AccountInterface.

The reason why we need an account proxy is that we don't want to have global state directly stored in the container.

This proxy object avoids multiple invocations of the authentication manager which can happen if the current user is accessed in constructors. It also allows legacy code to change the current user where the user cannot be directly injected into dependent code.

Hierarchy

Expanded class hierarchy of AccountProxy

1 file declares its use of AccountProxy
AccountProxyTest.php in core/tests/Drupal/Tests/Core/Session/AccountProxyTest.php
1 string reference to 'AccountProxy'
core.services.yml in core/core.services.yml
core/core.services.yml
1 service uses AccountProxy
current_user in core/core.services.yml
Drupal\Core\Session\AccountProxy

File

core/lib/Drupal/Core/Session/AccountProxy.php, line 19

Namespace

Drupal\Core\Session
View source
class AccountProxy implements AccountProxyInterface {
  use DependencySerializationTrait;

  /**
   * The instantiated account.
   *
   * @var \Drupal\Core\Session\AccountInterface
   */
  protected $account;

  /**
   * Account id.
   *
   * @var int
   */
  protected $id = 0;

  /**
   * Event dispatcher.
   *
   * @var \Symfony\Contracts\EventDispatcher\EventDispatcherInterface
   */
  protected $eventDispatcher;

  /**
   * AccountProxy constructor.
   *
   * @param \Symfony\Contracts\EventDispatcher\EventDispatcherInterface $eventDispatcher
   *   Event dispatcher.
   */
  public function __construct(EventDispatcherInterface $eventDispatcher) {
    $this->eventDispatcher = $eventDispatcher;
  }

  /**
   * {@inheritdoc}
   */
  public function setAccount(AccountInterface $account) {

    // If the passed account is already proxied, use the actual account instead
    // to prevent loops.
    if ($account instanceof static) {
      $account = $account
        ->getAccount();
    }
    $this->account = $account;
    $this->id = $account
      ->id();
    $this->eventDispatcher
      ->dispatch(new AccountSetEvent($account), AccountEvents::SET_USER);
  }

  /**
   * {@inheritdoc}
   */
  public function getAccount() {
    if (!isset($this->account)) {
      if ($this->id) {

        // After the container is rebuilt, DrupalKernel sets the initial
        // account to the id of the logged in user. This is necessary in order
        // to refresh the user account reference here.
        $this
          ->setAccount($this
          ->loadUserEntity($this->id));
      }
      else {
        $this->account = new AnonymousUserSession();
      }
    }
    return $this->account;
  }

  /**
   * {@inheritdoc}
   */
  public function id() {
    return $this->id;
  }

  /**
   * {@inheritdoc}
   */
  public function getRoles($exclude_locked_roles = FALSE) {
    return $this
      ->getAccount()
      ->getRoles($exclude_locked_roles);
  }

  /**
   * {@inheritdoc}
   */
  public function hasPermission($permission) {
    return $this
      ->getAccount()
      ->hasPermission($permission);
  }

  /**
   * {@inheritdoc}
   */
  public function isAuthenticated() {
    return $this
      ->getAccount()
      ->isAuthenticated();
  }

  /**
   * {@inheritdoc}
   */
  public function isAnonymous() {
    return $this
      ->getAccount()
      ->isAnonymous();
  }

  /**
   * {@inheritdoc}
   */
  public function getPreferredLangcode($fallback_to_default = TRUE) {
    return $this
      ->getAccount()
      ->getPreferredLangcode($fallback_to_default);
  }

  /**
   * {@inheritdoc}
   */
  public function getPreferredAdminLangcode($fallback_to_default = TRUE) {
    return $this
      ->getAccount()
      ->getPreferredAdminLangcode($fallback_to_default);
  }

  /**
   * {@inheritdoc}
   */
  public function getAccountName() {
    return $this
      ->getAccount()
      ->getAccountName();
  }

  /**
   * {@inheritdoc}
   */
  public function getDisplayName() {
    return $this
      ->getAccount()
      ->getDisplayName();
  }

  /**
   * {@inheritdoc}
   */
  public function getEmail() {
    return $this
      ->getAccount()
      ->getEmail();
  }

  /**
   * {@inheritdoc}
   */
  public function getTimeZone() {
    return $this
      ->getAccount()
      ->getTimeZone();
  }

  /**
   * {@inheritdoc}
   */
  public function getLastAccessedTime() {
    return $this
      ->getAccount()
      ->getLastAccessedTime();
  }

  /**
   * {@inheritdoc}
   */
  public function setInitialAccountId($account_id) {
    if (isset($this->account)) {
      throw new \LogicException('AccountProxyInterface::setInitialAccountId() cannot be called after an account was set on the AccountProxy');
    }
    $this->id = $account_id;
  }

  /**
   * Load a user entity.
   *
   * The entity type manager requires additional initialization code and cache
   * clearing after the list of modules is changed. Therefore it is necessary to
   * retrieve it as late as possible.
   *
   * Because of serialization issues it is currently not possible to inject the
   * container into the AccountProxy. Thus it is necessary to retrieve the
   * entity type manager statically.
   *
   * @see https://www.drupal.org/node/2430447
   *
   * @param int $account_id
   *   The id of an account to load.
   *
   * @return \Drupal\Core\Session\AccountInterface|null
   *   An account or NULL if none is found.
   */
  protected function loadUserEntity($account_id) {
    return \Drupal::entityTypeManager()
      ->getStorage('user')
      ->load($account_id);
  }

}

Members

Namesort descending Modifiers Type Description Overrides
AccountInterface::ANONYMOUS_ROLE constant Role ID for anonymous users.
AccountInterface::AUTHENTICATED_ROLE constant Role ID for authenticated users.
AccountProxy::$account protected property The instantiated account.
AccountProxy::$eventDispatcher protected property Event dispatcher.
AccountProxy::$id protected property Account id.
AccountProxy::getAccount public function Gets the currently wrapped account. Overrides AccountProxyInterface::getAccount
AccountProxy::getAccountName public function Returns the unaltered login name of this account. Overrides AccountInterface::getAccountName
AccountProxy::getDisplayName public function Returns the display name of this account. Overrides AccountInterface::getDisplayName
AccountProxy::getEmail public function Returns the email address of this account. Overrides AccountInterface::getEmail
AccountProxy::getLastAccessedTime public function The timestamp when the account last accessed the site. Overrides AccountInterface::getLastAccessedTime
AccountProxy::getPreferredAdminLangcode public function Returns the preferred administrative language code of the account. Overrides AccountInterface::getPreferredAdminLangcode
AccountProxy::getPreferredLangcode public function Returns the preferred language code of the account. Overrides AccountInterface::getPreferredLangcode
AccountProxy::getRoles public function Returns a list of roles. Overrides AccountInterface::getRoles
AccountProxy::getTimeZone public function Returns the timezone of this account. Overrides AccountInterface::getTimeZone
AccountProxy::hasPermission public function Checks whether a user has a certain permission. Overrides AccountInterface::hasPermission
AccountProxy::id public function Returns the user ID or 0 for anonymous. Overrides AccountInterface::id
AccountProxy::isAnonymous public function Returns TRUE if the account is anonymous. Overrides AccountInterface::isAnonymous
AccountProxy::isAuthenticated public function Returns TRUE if the account is authenticated. Overrides AccountInterface::isAuthenticated
AccountProxy::loadUserEntity protected function Load a user entity.
AccountProxy::setAccount public function Sets the currently wrapped account. Overrides AccountProxyInterface::setAccount
AccountProxy::setInitialAccountId public function Sets the id of the initial account. Overrides AccountProxyInterface::setInitialAccountId
AccountProxy::__construct public function AccountProxy constructor.
DependencySerializationTrait::$_entityStorages protected property
DependencySerializationTrait::$_serviceIds protected property
DependencySerializationTrait::__sleep public function 2
DependencySerializationTrait::__wakeup public function 2