29use Psr\Log\LoggerInterface;
30use Psr\Log\NullLogger;
31use Wikimedia\AtEase\AtEase;
61 $this->setEnableFlags(
64 $manager->setupPHPSessionHandler( $this );
75 private function setEnableFlags( $PHPSessionHandling ) {
76 switch ( $PHPSessionHandling ) {
88 $this->enable =
false;
107 return self::$instance && self::$instance->enable;
115 if ( self::$instance ) {
116 $manager->setupPHPSessionHandler( self::$instance );
121 if ( defined(
'MW_NO_SESSION_HANDLER' ) ) {
122 throw new \BadMethodCallException(
'MW_NO_SESSION_HANDLER is defined' );
126 self::$instance =
new self(
$manager );
129 session_write_close();
132 AtEase::suppressWarnings();
136 ini_set(
'session.use_cookies', 0 );
142 session_cache_limiter(
'' );
145 \Wikimedia\PhpSessionSerializer::setSerializeHandler();
149 session_set_save_handler( self::$instance,
true );
151 AtEase::restoreWarnings();
165 if ( $this->manager !==
$manager ) {
167 if ( $this->manager ) {
168 session_write_close();
173 \Wikimedia\PhpSessionSerializer::setLogger( $this->logger );
184 #[\ReturnTypeWillChange]
185 public function open( $save_path, $session_name ) {
186 if ( self::$instance !== $this ) {
187 throw new \UnexpectedValueException( __METHOD__ .
': Wrong instance called!' );
189 if ( !$this->enable ) {
190 throw new \BadMethodCallException(
'Attempt to use PHP session management' );
200 #[\ReturnTypeWillChange]
202 if ( self::$instance !== $this ) {
203 throw new \UnexpectedValueException( __METHOD__ .
': Wrong instance called!' );
205 $this->sessionFieldCache = [];
215 #[\ReturnTypeWillChange]
217 if ( self::$instance !== $this ) {
218 throw new \UnexpectedValueException( __METHOD__ .
': Wrong instance called!' );
220 if ( !$this->enable ) {
221 throw new \BadMethodCallException(
'Attempt to use PHP session management' );
224 $session = $this->manager->getSessionById( $id,
false );
230 $data = iterator_to_array( $session );
231 $this->sessionFieldCache[$id] = $data;
232 return (
string)\Wikimedia\PhpSessionSerializer::encode( $data );
244 #[\ReturnTypeWillChange]
245 public function write( $id, $dataStr ) {
246 if ( self::$instance !== $this ) {
247 throw new \UnexpectedValueException( __METHOD__ .
': Wrong instance called!' );
249 if ( !$this->enable ) {
250 throw new \BadMethodCallException(
'Attempt to use PHP session management' );
253 $session = $this->manager->getSessionById( $id,
true );
257 $this->logger->warning(
258 __METHOD__ .
': Session "{session}" cannot be loaded, skipping write.',
266 $data = \Wikimedia\PhpSessionSerializer::decode( $dataStr );
267 if ( $data ===
null ) {
275 $cache = $this->sessionFieldCache[$id] ?? [];
276 foreach ( $data as $key => $value ) {
277 if ( !array_key_exists( $key,
$cache ) ) {
278 if ( $session->exists( $key ) ) {
280 $this->logger->warning(
281 __METHOD__ .
": Key \"$key\" added in both Session and \$_SESSION!"
285 $session->set( $key, $value );
288 } elseif (
$cache[$key] === $value ) {
290 } elseif ( !$session->exists( $key ) ) {
292 $this->logger->warning(
293 __METHOD__ .
": Key \"$key\" deleted in Session and changed in \$_SESSION!"
295 $session->set( $key, $value );
297 } elseif (
$cache[$key] === $session->get( $key ) ) {
299 $session->set( $key, $value );
303 $this->logger->warning(
304 __METHOD__ .
": Key \"$key\" changed in both Session and \$_SESSION!"
310 \Wikimedia\PhpSessionSerializer::setLogger(
new NullLogger() );
311 foreach (
$cache as $key => $value ) {
312 if ( !array_key_exists( $key, $data ) && $session->exists( $key ) &&
313 \
Wikimedia\PhpSessionSerializer::encode( [ $key =>
true ] )
315 if ( $value === $session->get( $key ) ) {
317 $session->remove( $key );
321 $this->logger->warning(
322 __METHOD__ .
": Key \"$key\" changed in Session and deleted in \$_SESSION!"
327 \Wikimedia\PhpSessionSerializer::setLogger( $this->logger );
333 $this->logger->warning(
'Something wrote to $_SESSION!' );
337 $this->sessionFieldCache[$id] = iterator_to_array( $session );
351 #[\ReturnTypeWillChange]
353 if ( self::$instance !== $this ) {
354 throw new \UnexpectedValueException( __METHOD__ .
': Wrong instance called!' );
356 if ( !$this->enable ) {
357 throw new \BadMethodCallException(
'Attempt to use PHP session management' );
359 $session = $this->manager->getSessionById( $id,
false );
373 #[\ReturnTypeWillChange]
374 public function gc( $maxlifetime ) {
375 if ( self::$instance !== $this ) {
376 throw new \UnexpectedValueException( __METHOD__ .
': Wrong instance called!' );
378 $before = date(
'YmdHis', time() );
379 $this->store->deleteObjectsExpiringBefore( $before );
wfDeprecated( $function, $version=false, $component=false, $callerOffset=2)
Logs a warning that a deprecated feature was used.
Class representing a cache/ephemeral data store.
A class containing constants representing the names of configuration variables.
const PHPSessionHandling
Name constant for the PHPSessionHandling setting, for use with Config::get()