AccountProxy.php 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199
  1. <?php
  2. namespace Drupal\Core\Session;
  3. /**
  4. * A proxied implementation of AccountInterface.
  5. *
  6. * The reason why we need an account proxy is that we don't want to have global
  7. * state directly stored in the container.
  8. *
  9. * This proxy object avoids multiple invocations of the authentication manager
  10. * which can happen if the current user is accessed in constructors. It also
  11. * allows legacy code to change the current user where the user cannot be
  12. * directly injected into dependent code.
  13. */
  14. class AccountProxy implements AccountProxyInterface {
  15. /**
  16. * The instantiated account.
  17. *
  18. * @var \Drupal\Core\Session\AccountInterface
  19. */
  20. protected $account;
  21. /**
  22. * Account id.
  23. *
  24. * @var int
  25. */
  26. protected $id = 0;
  27. /**
  28. * Initial account id.
  29. *
  30. * @var int
  31. *
  32. * @deprecated Scheduled for removal in Drupal 8.4.x. Use $this->id instead.
  33. */
  34. protected $initialAccountId;
  35. /**
  36. * {@inheritdoc}
  37. */
  38. public function setAccount(AccountInterface $account) {
  39. // If the passed account is already proxied, use the actual account instead
  40. // to prevent loops.
  41. if ($account instanceof static) {
  42. $account = $account->getAccount();
  43. }
  44. $this->account = $account;
  45. $this->id = $account->id();
  46. date_default_timezone_set(drupal_get_user_timezone());
  47. }
  48. /**
  49. * {@inheritdoc}
  50. */
  51. public function getAccount() {
  52. if (!isset($this->account)) {
  53. if ($this->id) {
  54. // After the container is rebuilt, DrupalKernel sets the initial
  55. // account to the id of the logged in user. This is necessary in order
  56. // to refresh the user account reference here.
  57. $this->setAccount($this->loadUserEntity($this->id));
  58. }
  59. else {
  60. $this->account = new AnonymousUserSession();
  61. }
  62. }
  63. return $this->account;
  64. }
  65. /**
  66. * {@inheritdoc}
  67. */
  68. public function id() {
  69. return $this->id;
  70. }
  71. /**
  72. * {@inheritdoc}
  73. */
  74. public function getRoles($exclude_locked_roles = FALSE) {
  75. return $this->getAccount()->getRoles($exclude_locked_roles);
  76. }
  77. /**
  78. * {@inheritdoc}
  79. */
  80. public function hasPermission($permission) {
  81. return $this->getAccount()->hasPermission($permission);
  82. }
  83. /**
  84. * {@inheritdoc}
  85. */
  86. public function isAuthenticated() {
  87. return $this->getAccount()->isAuthenticated();
  88. }
  89. /**
  90. * {@inheritdoc}
  91. */
  92. public function isAnonymous() {
  93. return $this->getAccount()->isAnonymous();
  94. }
  95. /**
  96. * {@inheritdoc}
  97. */
  98. public function getPreferredLangcode($fallback_to_default = TRUE) {
  99. return $this->getAccount()->getPreferredLangcode($fallback_to_default);
  100. }
  101. /**
  102. * {@inheritdoc}
  103. */
  104. public function getPreferredAdminLangcode($fallback_to_default = TRUE) {
  105. return $this->getAccount()->getPreferredAdminLangcode($fallback_to_default);
  106. }
  107. /**
  108. * {@inheritdoc}
  109. */
  110. public function getUsername() {
  111. return $this->getAccountName();
  112. }
  113. /**
  114. * {@inheritdoc}
  115. */
  116. public function getAccountName() {
  117. return $this->getAccount()->getAccountName();
  118. }
  119. /**
  120. * {@inheritdoc}
  121. */
  122. public function getDisplayName() {
  123. return $this->getAccount()->getDisplayName();
  124. }
  125. /**
  126. * {@inheritdoc}
  127. */
  128. public function getEmail() {
  129. return $this->getAccount()->getEmail();
  130. }
  131. /**
  132. * {@inheritdoc}
  133. */
  134. public function getTimeZone() {
  135. return $this->getAccount()->getTimeZone();
  136. }
  137. /**
  138. * {@inheritdoc}
  139. */
  140. public function getLastAccessedTime() {
  141. return $this->getAccount()->getLastAccessedTime();
  142. }
  143. /**
  144. * {@inheritdoc}
  145. */
  146. public function setInitialAccountId($account_id) {
  147. if (isset($this->account)) {
  148. throw new \LogicException('AccountProxyInterface::setInitialAccountId() cannot be called after an account was set on the AccountProxy');
  149. }
  150. $this->id = $this->initialAccountId = $account_id;
  151. }
  152. /**
  153. * Load a user entity.
  154. *
  155. * The entity manager requires additional initialization code and cache
  156. * clearing after the list of modules is changed. Therefore it is necessary to
  157. * retrieve it as late as possible.
  158. *
  159. * Because of serialization issues it is currently not possible to inject the
  160. * container into the AccountProxy. Thus it is necessary to retrieve the
  161. * entity manager statically.
  162. *
  163. * @see https://www.drupal.org/node/2430447
  164. *
  165. * @param int $account_id
  166. * The id of an account to load.
  167. *
  168. * @return \Drupal\Core\Session\AccountInterface|null
  169. * An account or NULL if none is found.
  170. */
  171. protected function loadUserEntity($account_id) {
  172. return \Drupal::entityManager()->getStorage('user')->load($account_id);
  173. }
  174. }