Chris@0
|
1 <?php
|
Chris@0
|
2
|
Chris@0
|
3 namespace Drupal\Core\Session;
|
Chris@0
|
4
|
Chris@0
|
5 /**
|
Chris@0
|
6 * An implementation of AccountSwitcherInterface.
|
Chris@0
|
7 *
|
Chris@0
|
8 * This allows for safe switching of user accounts by ensuring that session
|
Chris@0
|
9 * data for one user is not leaked in to others. It also provides a stack that
|
Chris@0
|
10 * allows reverting to a previous user after switching.
|
Chris@0
|
11 */
|
Chris@0
|
12 class AccountSwitcher implements AccountSwitcherInterface {
|
Chris@0
|
13
|
Chris@0
|
14 /**
|
Chris@0
|
15 * A stack of previous overridden accounts.
|
Chris@0
|
16 *
|
Chris@0
|
17 * @var \Drupal\Core\Session\AccountInterface[]
|
Chris@0
|
18 */
|
Chris@0
|
19 protected $accountStack = [];
|
Chris@0
|
20
|
Chris@0
|
21 /**
|
Chris@0
|
22 * The current user service.
|
Chris@0
|
23 *
|
Chris@0
|
24 * @var \Drupal\Core\Session\AccountProxyInterface
|
Chris@0
|
25 */
|
Chris@0
|
26 protected $currentUser = [];
|
Chris@0
|
27
|
Chris@0
|
28 /**
|
Chris@0
|
29 * The write-safe session handler.
|
Chris@0
|
30 *
|
Chris@0
|
31 * @var \Drupal\Core\Session\WriteSafeSessionHandlerInterface
|
Chris@0
|
32 */
|
Chris@0
|
33 protected $writeSafeHandler;
|
Chris@0
|
34
|
Chris@0
|
35 /**
|
Chris@0
|
36 * The original state of session saving prior to account switching.
|
Chris@0
|
37 *
|
Chris@0
|
38 * @var bool
|
Chris@0
|
39 */
|
Chris@0
|
40 protected $originalSessionSaving;
|
Chris@0
|
41
|
Chris@0
|
42 /**
|
Chris@0
|
43 * Constructs a new AccountSwitcher.
|
Chris@0
|
44 *
|
Chris@0
|
45 * @param \Drupal\Core\Session\AccountProxyInterface $current_user
|
Chris@0
|
46 * The current user service.
|
Chris@0
|
47 * @param \Drupal\Core\Session\WriteSafeSessionHandlerInterface $write_safe_handler
|
Chris@0
|
48 * The write-safe session handler.
|
Chris@0
|
49 */
|
Chris@0
|
50 public function __construct(AccountProxyInterface $current_user, WriteSafeSessionHandlerInterface $write_safe_handler) {
|
Chris@0
|
51 $this->currentUser = $current_user;
|
Chris@0
|
52 $this->writeSafeHandler = $write_safe_handler;
|
Chris@0
|
53 }
|
Chris@0
|
54
|
Chris@0
|
55 /**
|
Chris@0
|
56 * {@inheritdoc}
|
Chris@0
|
57 */
|
Chris@0
|
58 public function switchTo(AccountInterface $account) {
|
Chris@0
|
59 // Prevent session information from being saved and push previous account.
|
Chris@0
|
60 if (!isset($this->originalSessionSaving)) {
|
Chris@0
|
61 // Ensure that only the first session saving status is saved.
|
Chris@0
|
62 $this->originalSessionSaving = $this->writeSafeHandler->isSessionWritable();
|
Chris@0
|
63 }
|
Chris@0
|
64 $this->writeSafeHandler->setSessionWritable(FALSE);
|
Chris@0
|
65 array_push($this->accountStack, $this->currentUser->getAccount());
|
Chris@0
|
66 $this->currentUser->setAccount($account);
|
Chris@0
|
67 return $this;
|
Chris@0
|
68 }
|
Chris@0
|
69
|
Chris@0
|
70 /**
|
Chris@0
|
71 * {@inheritdoc}
|
Chris@0
|
72 */
|
Chris@0
|
73 public function switchBack() {
|
Chris@0
|
74 // Restore the previous account from the stack.
|
Chris@0
|
75 if (!empty($this->accountStack)) {
|
Chris@0
|
76 $this->currentUser->setAccount(array_pop($this->accountStack));
|
Chris@0
|
77 }
|
Chris@0
|
78 else {
|
Chris@0
|
79 throw new \RuntimeException('No more accounts to revert to.');
|
Chris@0
|
80 }
|
Chris@0
|
81 // Restore original session saving status if all account switches are
|
Chris@0
|
82 // reverted.
|
Chris@0
|
83 if (empty($this->accountStack)) {
|
Chris@0
|
84 if ($this->originalSessionSaving) {
|
Chris@0
|
85 $this->writeSafeHandler->setSessionWritable(TRUE);
|
Chris@0
|
86 }
|
Chris@0
|
87 }
|
Chris@0
|
88 return $this;
|
Chris@0
|
89 }
|
Chris@0
|
90
|
Chris@0
|
91 }
|