Bitrix-D7 23.9
 
Загрузка...
Поиск...
Не найдено
abstractsessionhandler.php
1<?php
2
4
9
10abstract class AbstractSessionHandler implements \SessionHandlerInterface, \SessionUpdateTimestampHandlerInterface, \SessionIdInterface
11{
12 public const LOCK_ERROR_MESSAGE = 'Unable to get session lock within 60 seconds.';
13
15 protected $readOnly = false;
17 protected $sessionId;
19 private $prefetchId;
21 private $prefetchData;
23 private $lastCreatedId;
25 private $listValidatedIds = [];
27 private $releaseLockAfterClose = true;
28
29 #[\ReturnTypeWillChange]
30 public function read($sessionId)
31 {
32 if (!$this->validateSessionId($sessionId))
33 {
34 return '';
35 }
36
37 $this->sessionId = $sessionId;
38 if ($this->prefetchId !== null)
39 {
40 $prefetchId = $this->prefetchId;
41 $prefetchData = $this->prefetchData;
42
43 $this->prefetchId = null;
44 $this->prefetchData = null;
45
46 if ($prefetchId === $this->sessionId)
47 {
48 return $prefetchData;
49 }
50 }
51
52 if (!$this->readOnly && !$this->lock($this->sessionId))
53 {
54 $this->triggerLockFatalError();
55 }
56
57 return $this->processRead($sessionId);
58 }
59
60 abstract protected function processRead($sessionId): string;
61
62 protected function triggerLockFatalError(string $additionalText = ''): void
63 {
65 if ($additionalText)
66 {
67 $text .= $additionalText;
68 }
69
70 $httpResponse = new HttpResponse();
71 $httpResponse->setStatus('500 Internal Server Error');
72 trigger_error($text, E_USER_ERROR);
73 Application::getInstance()->end(0, $httpResponse);
74 }
75
76 public function write($sessionId, $sessionData): bool
77 {
78 if (!$this->validateSessionId($sessionId))
79 {
80 return false;
81 }
82
83 if ($this->readOnly)
84 {
85 return true;
86 }
87
88 return $this->processWrite($sessionId, $sessionData);
89 }
90
91 abstract protected function processWrite($sessionId, $sessionData): bool;
92
93 abstract protected function lock($sessionId): bool;
94
95 abstract protected function unlock($sessionId): bool;
96
97 private function releaseLocksAfterValidate(): void
98 {
99 unset($this->listValidatedIds[$this->sessionId]);
100 foreach ($this->listValidatedIds as $mustBeUnlockedId => $true)
101 {
102 $this->unlock($mustBeUnlockedId);
103 unset($this->listValidatedIds[$this->sessionId]);
104 }
105 }
106
107 public function close(): bool
108 {
109 if (!$this->readOnly && $this->validateSessionId($this->sessionId))
110 {
111 if (isSessionExpired())
112 {
113 $this->destroy($this->sessionId);
114 }
115
116 if ($this->releaseLockAfterClose)
117 {
118 $this->unlock($this->sessionId);
119 }
120
121 $this->releaseLocksAfterValidate();
122 }
123
124 $this->sessionId = null;
125 $this->lastCreatedId = null;
126
127 return true;
128 }
129
130 public function destroy($sessionId): bool
131 {
132 if ($this->readOnly)
133 {
134 return true;
135 }
136
137 if (!$this->validateSessionId($sessionId))
138 {
139 return false;
140 }
141
142 $result = $this->processDestroy($sessionId);
143 $this->lastCreatedId = null;
144
145 return $result;
146 }
147
148 abstract protected function processDestroy($sessionId): bool;
149
150 public function validateId($sessionId): bool
151 {
152 $this->listValidatedIds[$sessionId] = true;
153
154 $this->prefetchData = $this->read($sessionId);
155 $this->prefetchId = $sessionId;
156
157 return $this->prefetchData !== '';
158 }
159
160 public function create_sid(): string
161 {
162 $this->lastCreatedId = Random::getString(32, true);
163
164 return $this->lastCreatedId;
165 }
166
167 protected function validateSessionId($sessionId): bool
168 {
169 return
170 $sessionId &&
171 is_string($sessionId) &&
172 preg_match('/^[\da-z\-,]{6,}$/iD', $sessionId)
173 ;
174 }
175
177 {
178 $this->releaseLockAfterClose = false;
179 }
180
182 {
183 $this->releaseLockAfterClose = true;
184 }
185}