26 use Psr\Log\LoggerInterface;
72 switch ( $PHPSessionHandling ) {
84 $this->enable =
false;
103 return self::$instance && self::$instance->enable;
111 if ( self::$instance ) {
117 if ( defined(
'MW_NO_SESSION_HANDLER' ) ) {
118 throw new \BadMethodCallException(
'MW_NO_SESSION_HANDLER is defined' );
122 self::$instance =
new self(
$manager );
125 session_write_close();
128 \Wikimedia\suppressWarnings();
131 ini_set(
'session.use_cookies', 0 );
132 ini_set(
'session.use_trans_sid', 0 );
138 session_cache_limiter(
'' );
141 \Wikimedia\PhpSessionSerializer::setSerializeHandler();
145 session_set_save_handler( self::$instance,
true );
147 \Wikimedia\restoreWarnings();
161 if ( $this->manager !==
$manager ) {
163 if ( $this->manager ) {
164 session_write_close();
169 \Wikimedia\PhpSessionSerializer::setLogger( $this->logger );
180 public function open( $save_path, $session_name ) {
181 if ( self::$instance !== $this ) {
182 throw new \UnexpectedValueException( __METHOD__ .
': Wrong instance called!' );
184 if ( !$this->enable ) {
185 throw new \BadMethodCallException(
'Attempt to use PHP session management' );
196 if ( self::$instance !== $this ) {
197 throw new \UnexpectedValueException( __METHOD__ .
': Wrong instance called!' );
199 $this->sessionFieldCache = [];
210 if ( self::$instance !== $this ) {
211 throw new \UnexpectedValueException( __METHOD__ .
': Wrong instance called!' );
213 if ( !$this->enable ) {
214 throw new \BadMethodCallException(
'Attempt to use PHP session management' );
217 $session = $this->manager->getSessionById( $id,
false );
223 $data = iterator_to_array( $session );
224 $this->sessionFieldCache[$id] =
$data;
225 return (
string)\Wikimedia\PhpSessionSerializer::encode(
$data );
237 public function write( $id, $dataStr ) {
238 if ( self::$instance !== $this ) {
239 throw new \UnexpectedValueException( __METHOD__ .
': Wrong instance called!' );
241 if ( !$this->enable ) {
242 throw new \BadMethodCallException(
'Attempt to use PHP session management' );
245 $session = $this->manager->getSessionById( $id,
true );
249 $this->logger->warning(
250 __METHOD__ .
': Session "{session}" cannot be loaded, skipping write.',
258 $data = \Wikimedia\PhpSessionSerializer::decode( $dataStr );
259 if (
$data ===
null ) {
267 $cache = $this->sessionFieldCache[$id] ?? [];
269 if ( !array_key_exists( $key,
$cache ) ) {
270 if ( $session->exists( $key ) ) {
272 $this->logger->warning(
273 __METHOD__ .
": Key \"$key\" added in both Session and \$_SESSION!"
277 $session->set( $key,
$value );
282 } elseif ( !$session->exists( $key ) ) {
284 $this->logger->warning(
285 __METHOD__ .
": Key \"$key\" deleted in Session and changed in \$_SESSION!"
287 $session->set( $key,
$value );
289 } elseif (
$cache[$key] === $session->get( $key ) ) {
291 $session->set( $key,
$value );
295 $this->logger->warning(
296 __METHOD__ .
": Key \"$key\" changed in both Session and \$_SESSION!"
302 \Wikimedia\PhpSessionSerializer::setLogger(
new \Psr\Log\NullLogger() );
304 if ( !array_key_exists( $key,
$data ) && $session->exists( $key ) &&
305 \Wikimedia\PhpSessionSerializer::encode( [ $key =>
true ] )
307 if (
$cache[$key] === $session->get( $key ) ) {
309 $session->remove( $key );
313 $this->logger->warning(
314 __METHOD__ .
": Key \"$key\" changed in Session and deleted in \$_SESSION!"
319 \Wikimedia\PhpSessionSerializer::setLogger( $this->logger );
325 $this->logger->warning(
'Something wrote to $_SESSION!' );
329 $this->sessionFieldCache[$id] = iterator_to_array( $session );
344 if ( self::$instance !== $this ) {
345 throw new \UnexpectedValueException( __METHOD__ .
': Wrong instance called!' );
347 if ( !$this->enable ) {
348 throw new \BadMethodCallException(
'Attempt to use PHP session management' );
350 $session = $this->manager->getSessionById( $id,
false );
364 public function gc( $maxlifetime ) {
365 if ( self::$instance !== $this ) {
366 throw new \UnexpectedValueException( __METHOD__ .
': Wrong instance called!' );
368 $before = date(
'YmdHis', time() );
369 $this->store->deleteObjectsExpiringBefore( $before );