26 use Psr\Log\LoggerInterface;
70 switch ( $PHPSessionHandling ) {
82 $this->enable =
false;
101 return self::$instance && self::$instance->enable;
109 if ( self::$instance ) {
115 if ( defined(
'MW_NO_SESSION_HANDLER' ) ) {
116 throw new \BadMethodCallException(
'MW_NO_SESSION_HANDLER is defined' );
120 self::$instance =
new self(
$manager );
123 session_write_close();
126 \Wikimedia\suppressWarnings();
129 ini_set(
'session.use_cookies', 0 );
130 ini_set(
'session.use_trans_sid', 0 );
136 session_cache_limiter(
'' );
139 \Wikimedia\PhpSessionSerializer::setSerializeHandler();
143 session_set_save_handler( self::$instance,
true );
145 \Wikimedia\restoreWarnings();
159 if ( $this->manager !==
$manager ) {
161 if ( $this->manager ) {
162 session_write_close();
167 \Wikimedia\PhpSessionSerializer::setLogger( $this->logger );
185 return defined(
'HHVM_VERSION' ) || version_compare( PHP_VERSION,
'7.0.0',
'>=' ) ?
true : 0;
195 return defined(
'HHVM_VERSION' ) || version_compare( PHP_VERSION,
'7.0.0',
'>=' ) ?
false : -1;
205 public function open( $save_path, $session_name ) {
206 if ( self::$instance !== $this ) {
207 throw new \UnexpectedValueException( __METHOD__ .
': Wrong instance called!' );
209 if ( !$this->enable ) {
210 throw new \BadMethodCallException(
'Attempt to use PHP session management' );
221 if ( self::$instance !== $this ) {
222 throw new \UnexpectedValueException( __METHOD__ .
': Wrong instance called!' );
224 $this->sessionFieldCache = [];
235 if ( self::$instance !== $this ) {
236 throw new \UnexpectedValueException( __METHOD__ .
': Wrong instance called!' );
238 if ( !$this->enable ) {
239 throw new \BadMethodCallException(
'Attempt to use PHP session management' );
242 $session = $this->manager->getSessionById( $id,
false );
248 $data = iterator_to_array( $session );
249 $this->sessionFieldCache[$id] = $data;
250 return (
string)\Wikimedia\PhpSessionSerializer::encode( $data );
262 public function write( $id, $dataStr ) {
263 if ( self::$instance !== $this ) {
264 throw new \UnexpectedValueException( __METHOD__ .
': Wrong instance called!' );
266 if ( !$this->enable ) {
267 throw new \BadMethodCallException(
'Attempt to use PHP session management' );
270 $session = $this->manager->getSessionById( $id,
true );
274 $this->logger->warning(
275 __METHOD__ .
': Session "{session}" cannot be loaded, skipping write.',
283 $data = \Wikimedia\PhpSessionSerializer::decode( $dataStr );
284 if ( $data ===
null ) {
292 $cache = isset( $this->sessionFieldCache[$id] ) ? $this->sessionFieldCache[$id] : [];
293 foreach ( $data
as $key =>
$value ) {
294 if ( !array_key_exists( $key,
$cache ) ) {
295 if ( $session->exists( $key ) ) {
297 $this->logger->warning(
298 __METHOD__ .
": Key \"$key\" added in both Session and \$_SESSION!"
302 $session->set( $key,
$value );
307 } elseif ( !$session->exists( $key ) ) {
309 $this->logger->warning(
310 __METHOD__ .
": Key \"$key\" deleted in Session and changed in \$_SESSION!"
312 $session->set( $key,
$value );
314 } elseif (
$cache[$key] === $session->get( $key ) ) {
316 $session->set( $key,
$value );
320 $this->logger->warning(
321 __METHOD__ .
": Key \"$key\" changed in both Session and \$_SESSION!"
327 \Wikimedia\PhpSessionSerializer::setLogger(
new \Psr\Log\NullLogger() );
329 if ( !array_key_exists( $key, $data ) && $session->exists( $key ) &&
330 \
Wikimedia\PhpSessionSerializer::encode( [ $key =>
true ] )
332 if (
$cache[$key] === $session->get( $key ) ) {
334 $session->remove( $key );
338 $this->logger->warning(
339 __METHOD__ .
": Key \"$key\" changed in Session and deleted in \$_SESSION!"
344 \Wikimedia\PhpSessionSerializer::setLogger( $this->logger );
350 $this->logger->warning(
'Something wrote to $_SESSION!' );
354 $this->sessionFieldCache[$id] = iterator_to_array( $session );
369 if ( self::$instance !== $this ) {
370 throw new \UnexpectedValueException( __METHOD__ .
': Wrong instance called!' );
372 if ( !$this->enable ) {
373 throw new \BadMethodCallException(
'Attempt to use PHP session management' );
375 $session = $this->manager->getSessionById( $id,
false );
389 public function gc( $maxlifetime ) {
390 if ( self::$instance !== $this ) {
391 throw new \UnexpectedValueException( __METHOD__ .
': Wrong instance called!' );
393 $before = date(
'YmdHis', time() );
394 $this->
store->deleteObjectsExpiringBefore( $before );