26 use Psr\Log\LoggerInterface;
28 use Psr\Log\NullLogger;
61 $manager->setupPHPSessionHandler( $this );
73 switch ( $PHPSessionHandling ) {
85 $this->enable =
false;
104 return self::$instance && self::$instance->enable;
112 if ( self::$instance ) {
113 $manager->setupPHPSessionHandler( self::$instance );
118 if ( defined(
'MW_NO_SESSION_HANDLER' ) ) {
119 throw new \BadMethodCallException(
'MW_NO_SESSION_HANDLER is defined' );
123 self::$instance =
new self(
$manager );
126 session_write_close();
129 \Wikimedia\suppressWarnings();
132 ini_set(
'session.use_cookies', 0 );
133 ini_set(
'session.use_trans_sid', 0 );
139 session_cache_limiter(
'' );
142 \Wikimedia\PhpSessionSerializer::setSerializeHandler();
146 session_set_save_handler( self::$instance,
true );
148 \Wikimedia\restoreWarnings();
162 if ( $this->manager !==
$manager ) {
164 if ( $this->manager ) {
165 session_write_close();
170 \Wikimedia\PhpSessionSerializer::setLogger( $this->logger );
181 public function open( $save_path, $session_name ) {
182 if ( self::$instance !== $this ) {
183 throw new \UnexpectedValueException( __METHOD__ .
': Wrong instance called!' );
185 if ( !$this->enable ) {
186 throw new \BadMethodCallException(
'Attempt to use PHP session management' );
197 if ( self::$instance !== $this ) {
198 throw new \UnexpectedValueException( __METHOD__ .
': Wrong instance called!' );
200 $this->sessionFieldCache = [];
211 if ( self::$instance !== $this ) {
212 throw new \UnexpectedValueException( __METHOD__ .
': Wrong instance called!' );
214 if ( !$this->enable ) {
215 throw new \BadMethodCallException(
'Attempt to use PHP session management' );
218 $session = $this->manager->getSessionById( $id,
false );
224 $data = iterator_to_array( $session );
225 $this->sessionFieldCache[$id] = $data;
226 return (
string)\Wikimedia\PhpSessionSerializer::encode( $data );
238 public function write( $id, $dataStr ) {
239 if ( self::$instance !== $this ) {
240 throw new \UnexpectedValueException( __METHOD__ .
': Wrong instance called!' );
242 if ( !$this->enable ) {
243 throw new \BadMethodCallException(
'Attempt to use PHP session management' );
246 $session = $this->manager->getSessionById( $id,
true );
250 $this->logger->warning(
251 __METHOD__ .
': Session "{session}" cannot be loaded, skipping write.',
259 $data = \Wikimedia\PhpSessionSerializer::decode( $dataStr );
260 if ( $data ===
null ) {
268 $cache = $this->sessionFieldCache[$id] ?? [];
269 foreach ( $data as $key => $value ) {
270 if ( !array_key_exists( $key,
$cache ) ) {
271 if ( $session->exists( $key ) ) {
273 $this->logger->warning(
274 __METHOD__ .
": Key \"$key\" added in both Session and \$_SESSION!"
278 $session->set( $key, $value );
281 } elseif (
$cache[$key] === $value ) {
283 } elseif ( !$session->exists( $key ) ) {
285 $this->logger->warning(
286 __METHOD__ .
": Key \"$key\" deleted in Session and changed in \$_SESSION!"
288 $session->set( $key, $value );
290 } elseif (
$cache[$key] === $session->get( $key ) ) {
292 $session->set( $key, $value );
296 $this->logger->warning(
297 __METHOD__ .
": Key \"$key\" changed in both Session and \$_SESSION!"
303 \Wikimedia\PhpSessionSerializer::setLogger(
new NullLogger() );
304 foreach (
$cache as $key => $value ) {
305 if ( !array_key_exists( $key, $data ) && $session->exists( $key ) &&
306 \Wikimedia\PhpSessionSerializer::encode( [ $key =>
true ] )
308 if (
$cache[$key] === $session->get( $key ) ) {
310 $session->remove( $key );
314 $this->logger->warning(
315 __METHOD__ .
": Key \"$key\" changed in Session and deleted in \$_SESSION!"
320 \Wikimedia\PhpSessionSerializer::setLogger( $this->logger );
326 $this->logger->warning(
'Something wrote to $_SESSION!' );
330 $this->sessionFieldCache[$id] = iterator_to_array( $session );
345 if ( self::$instance !== $this ) {
346 throw new \UnexpectedValueException( __METHOD__ .
': Wrong instance called!' );
348 if ( !$this->enable ) {
349 throw new \BadMethodCallException(
'Attempt to use PHP session management' );
351 $session = $this->manager->getSessionById( $id,
false );
365 public function gc( $maxlifetime ) {
366 if ( self::$instance !== $this ) {
367 throw new \UnexpectedValueException( __METHOD__ .
': Wrong instance called!' );
369 $before = date(
'YmdHis', time() );
370 $this->store->deleteObjectsExpiringBefore( $before );