AccountProxy.php 4.55 KB
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
<?php

namespace Drupal\Core\Session;

/**
 * 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.
 */
class AccountProxy implements AccountProxyInterface {

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

25 26 27 28 29 30 31
  /**
   * Account id.
   *
   * @var int
   */
  protected $id = 0;

32
  /**
33
   * Initial account id.
34
   *
35
   * @var int
36 37
   *
   * @deprecated Scheduled for removal in Drupal 8.4.x. Use $this->id instead.
38
   */
39
  protected $initialAccountId;
40 41 42 43 44

  /**
   * {@inheritdoc}
   */
  public function setAccount(AccountInterface $account) {
45
    // If the passed account is already proxied, use the actual account instead
46 47 48 49 50
    // to prevent loops.
    if ($account instanceof static) {
      $account = $account->getAccount();
    }
    $this->account = $account;
51
    $this->id = $account->id();
52
    date_default_timezone_set(drupal_get_user_timezone());
53 54 55 56 57 58 59
  }

  /**
   * {@inheritdoc}
   */
  public function getAccount() {
    if (!isset($this->account)) {
60
      if ($this->id) {
61 62 63
        // 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.
64
        $this->setAccount($this->loadUserEntity($this->id));
65 66 67 68
      }
      else {
        $this->account = new AnonymousUserSession();
      }
69
    }
70

71 72 73 74 75 76 77
    return $this->account;
  }

  /**
   * {@inheritdoc}
   */
  public function id() {
78
    return $this->id;
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
  }

  /**
   * {@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}
   */
112 113
  public function getPreferredLangcode($fallback_to_default = TRUE) {
    return $this->getAccount()->getPreferredLangcode($fallback_to_default);
114 115 116 117 118
  }

  /**
   * {@inheritdoc}
   */
119 120
  public function getPreferredAdminLangcode($fallback_to_default = TRUE) {
    return $this->getAccount()->getPreferredAdminLangcode($fallback_to_default);
121 122 123 124 125 126
  }

  /**
   * {@inheritdoc}
   */
  public function getUsername() {
127 128 129 130 131 132 133 134 135 136 137 138 139 140 141
    return $this->getAccountName();
  }

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

  /**
   * {@inheritdoc}
   */
  public function getDisplayName() {
    return $this->getAccount()->getDisplayName();
142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164
  }

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

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

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

165 166 167 168 169 170 171 172
  /**
   * {@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');
    }

173
    $this->id = $this->initialAccountId = $account_id;
174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191
  }

  /**
   * Load a user entity.
   *
   * The entity 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 manager statically.
   *
   * @see https://www.drupal.org/node/2430447
   *
   * @param int $account_id
   *   The id of an account to load.
   *
192
   * @return \Drupal\Core\Session\AccountInterface|null
193 194 195 196 197
   *   An account or NULL if none is found.
   */
  protected function loadUserEntity($account_id) {
    return \Drupal::entityManager()->getStorage('user')->load($account_id);
  }
198

199
}