28use Psr\Log\LoggerInterface;
29use Psr\Log\NullLogger;
30use SessionHandlerInterface;
31use Wikimedia\AtEase\AtEase;
33use Wikimedia\PhpSessionSerializer;
63 $this->setEnableFlags(
66 $manager->setupPHPSessionHandler( $this );
77 private function setEnableFlags( $PHPSessionHandling ) {
78 switch ( $PHPSessionHandling ) {
90 $this->enable =
false;
109 return self::$instance && self::$instance->enable;
117 if ( self::$instance ) {
118 $manager->setupPHPSessionHandler( self::$instance );
123 if ( defined(
'MW_NO_SESSION_HANDLER' ) ) {
124 throw new \BadMethodCallException(
'MW_NO_SESSION_HANDLER is defined' );
128 self::$instance =
new self(
$manager );
131 session_write_close();
134 AtEase::suppressWarnings();
137 ini_set(
'session.use_cookies', 0 );
143 session_cache_limiter(
'' );
146 PhpSessionSerializer::setSerializeHandler();
150 session_set_save_handler( self::$instance,
true );
152 AtEase::restoreWarnings();
166 if ( $this->manager !==
$manager ) {
168 if ( $this->manager ) {
169 session_write_close();
174 PhpSessionSerializer::setLogger( $this->logger );
185 #[\ReturnTypeWillChange]
186 public function open( $save_path, $session_name ) {
187 if ( self::$instance !== $this ) {
188 throw new \UnexpectedValueException( __METHOD__ .
': Wrong instance called!' );
190 if ( !$this->enable ) {
191 throw new \BadMethodCallException(
'Attempt to use PHP session management' );
201 #[\ReturnTypeWillChange]
203 if ( self::$instance !== $this ) {
204 throw new \UnexpectedValueException( __METHOD__ .
': Wrong instance called!' );
206 $this->sessionFieldCache = [];
216 #[\ReturnTypeWillChange]
218 if ( self::$instance !== $this ) {
219 throw new \UnexpectedValueException( __METHOD__ .
': Wrong instance called!' );
221 if ( !$this->enable ) {
222 throw new \BadMethodCallException(
'Attempt to use PHP session management' );
225 $session = $this->manager->getSessionById( $id,
false );
231 $data = iterator_to_array( $session );
232 $this->sessionFieldCache[$id] = $data;
233 return (
string)PhpSessionSerializer::encode( $data );
245 #[\ReturnTypeWillChange]
246 public function write( $id, $dataStr ) {
247 if ( self::$instance !== $this ) {
248 throw new \UnexpectedValueException( __METHOD__ .
': Wrong instance called!' );
250 if ( !$this->enable ) {
251 throw new \BadMethodCallException(
'Attempt to use PHP session management' );
254 $session = $this->manager->getSessionById( $id,
true );
258 $this->logger->warning(
259 __METHOD__ .
': Session "{session}" cannot be loaded, skipping write.',
267 $data = PhpSessionSerializer::decode( $dataStr );
268 if ( $data ===
null ) {
276 $cache = $this->sessionFieldCache[$id] ?? [];
277 foreach ( $data as $key => $value ) {
278 if ( !array_key_exists( $key, $cache ) ) {
279 if ( $session->exists( $key ) ) {
281 $this->logger->warning(
282 __METHOD__ .
": Key \"$key\" added in both Session and \$_SESSION!"
286 $session->set( $key, $value );
289 } elseif ( $cache[$key] === $value ) {
291 } elseif ( !$session->exists( $key ) ) {
293 $this->logger->warning(
294 __METHOD__ .
": Key \"$key\" deleted in Session and changed in \$_SESSION!"
296 $session->set( $key, $value );
298 } elseif ( $cache[$key] === $session->get( $key ) ) {
300 $session->set( $key, $value );
304 $this->logger->warning(
305 __METHOD__ .
": Key \"$key\" changed in both Session and \$_SESSION!"
311 PhpSessionSerializer::setLogger(
new NullLogger() );
312 foreach ( $cache as $key => $value ) {
313 if ( !array_key_exists( $key, $data ) && $session->exists( $key ) &&
314 PhpSessionSerializer::encode( [ $key =>
true ] )
316 if ( $value === $session->get( $key ) ) {
318 $session->remove( $key );
322 $this->logger->warning(
323 __METHOD__ .
": Key \"$key\" changed in Session and deleted in \$_SESSION!"
328 PhpSessionSerializer::setLogger( $this->logger );
334 $this->logger->warning(
'Something wrote to $_SESSION!' );
338 $this->sessionFieldCache[$id] = iterator_to_array( $session );
352 #[\ReturnTypeWillChange]
354 if ( self::$instance !== $this ) {
355 throw new \UnexpectedValueException( __METHOD__ .
': Wrong instance called!' );
357 if ( !$this->enable ) {
358 throw new \BadMethodCallException(
'Attempt to use PHP session management' );
360 $session = $this->manager->getSessionById( $id,
false );
374 #[\ReturnTypeWillChange]
375 public function gc( $maxlifetime ) {
376 if ( self::$instance !== $this ) {
377 throw new \UnexpectedValueException( __METHOD__ .
': Wrong instance called!' );
wfTimestampNow()
Convenience function; returns MediaWiki timestamp for the present time.
wfDeprecated( $function, $version=false, $component=false, $callerOffset=2)
Logs a warning that a deprecated feature was used.
A class containing constants representing the names of configuration variables.
const PHPSessionHandling
Name constant for the PHPSessionHandling setting, for use with Config::get()