get( self::getKey( $id ) ); if ( $data === false ) { return ''; } return $data; } /** * Callback when writing session data. * * @param string $id Session id * @param string $data Session data * @return bool Success */ static function write( $id, $data ) { global $wgObjectCacheSessionExpiry; self::getCache()->set( self::getKey( $id ), $data, $wgObjectCacheSessionExpiry ); return true; } /** * Callback to destroy a session when calling session_destroy(). * * @param string $id Session id * @return bool Success */ static function destroy( $id ) { self::getCache()->delete( self::getKey( $id ) ); return true; } /** * Callback to execute garbage collection. * NOP: Object caches perform garbage collection implicitly * * @param int $maxlifetime Maximum session life time * @return bool Success */ static function gc( $maxlifetime ) { return true; } /** * Shutdown function. * See the comment inside ObjectCacheSessionHandler::install for rationale. */ static function handleShutdown() { session_write_close(); } /** * Pre-emptive session renewal function */ static function renewCurrentSession() { global $wgObjectCacheSessionExpiry; // Once a session is at half TTL, renew it $window = $wgObjectCacheSessionExpiry / 2; $logger = LoggerFactory::getInstance( 'SessionHandler' ); $now = microtime( true ); // Session are only written in object stores when $_SESSION changes, // which also renews the TTL ($wgObjectCacheSessionExpiry). If a user // is active but not causing session data changes, it may suddenly // expire as they view a form, blocking the first submission. // Make a dummy change every so often to avoid this. if ( !isset( $_SESSION['wsExpiresUnix'] ) ) { $_SESSION['wsExpiresUnix'] = $now + $wgObjectCacheSessionExpiry; $logger->info( "Set expiry for session " . session_id(), array() ); } elseif ( ( $now + $window ) > $_SESSION['wsExpiresUnix'] ) { $_SESSION['wsExpiresUnix'] = $now + $wgObjectCacheSessionExpiry; $logger->info( "Renewed session " . session_id(), array() ); } } }