29use Psr\Log\LoggerInterface;
30use Psr\Log\NullLogger;
31use Wikimedia\AtEase\AtEase;
61 $this->setEnableFlags(
64 $manager->setupPHPSessionHandler( $this );
75 private function setEnableFlags( $PHPSessionHandling ) {
76 switch ( $PHPSessionHandling ) {
88 $this->enable =
false;
107 return self::$instance && self::$instance->enable;
115 if ( self::$instance ) {
116 $manager->setupPHPSessionHandler( self::$instance );
121 if ( defined(
'MW_NO_SESSION_HANDLER' ) ) {
122 throw new \BadMethodCallException(
'MW_NO_SESSION_HANDLER is defined' );
126 self::$instance =
new self(
$manager );
129 session_write_close();
132 AtEase::suppressWarnings();
136 ini_set(
'session.use_cookies', 0 );
138 ini_set(
'session.use_trans_sid', 0 );
144 session_cache_limiter(
'' );
147 \Wikimedia\PhpSessionSerializer::setSerializeHandler();
151 session_set_save_handler( self::$instance,
true );
153 AtEase::restoreWarnings();
167 if ( $this->manager !==
$manager ) {
169 if ( $this->manager ) {
170 session_write_close();
175 \Wikimedia\PhpSessionSerializer::setLogger( $this->logger );
186 #[\ReturnTypeWillChange]
187 public function open( $save_path, $session_name ) {
188 if ( self::$instance !== $this ) {
189 throw new \UnexpectedValueException( __METHOD__ .
': Wrong instance called!' );
191 if ( !$this->enable ) {
192 throw new \BadMethodCallException(
'Attempt to use PHP session management' );
202 #[\ReturnTypeWillChange]
204 if ( self::$instance !== $this ) {
205 throw new \UnexpectedValueException( __METHOD__ .
': Wrong instance called!' );
207 $this->sessionFieldCache = [];
217 #[\ReturnTypeWillChange]
219 if ( self::$instance !== $this ) {
220 throw new \UnexpectedValueException( __METHOD__ .
': Wrong instance called!' );
222 if ( !$this->enable ) {
223 throw new \BadMethodCallException(
'Attempt to use PHP session management' );
226 $session = $this->manager->getSessionById( $id,
false );
232 $data = iterator_to_array( $session );
233 $this->sessionFieldCache[$id] = $data;
234 return (
string)\Wikimedia\PhpSessionSerializer::encode( $data );
246 #[\ReturnTypeWillChange]
247 public function write( $id, $dataStr ) {
248 if ( self::$instance !== $this ) {
249 throw new \UnexpectedValueException( __METHOD__ .
': Wrong instance called!' );
251 if ( !$this->enable ) {
252 throw new \BadMethodCallException(
'Attempt to use PHP session management' );
255 $session = $this->manager->getSessionById( $id,
true );
259 $this->logger->warning(
260 __METHOD__ .
': Session "{session}" cannot be loaded, skipping write.',
268 $data = \Wikimedia\PhpSessionSerializer::decode( $dataStr );
269 if ( $data ===
null ) {
277 $cache = $this->sessionFieldCache[$id] ?? [];
278 foreach ( $data as $key => $value ) {
279 if ( !array_key_exists( $key, $cache ) ) {
280 if ( $session->exists( $key ) ) {
282 $this->logger->warning(
283 __METHOD__ .
": Key \"$key\" added in both Session and \$_SESSION!"
287 $session->set( $key, $value );
290 } elseif ( $cache[$key] === $value ) {
292 } elseif ( !$session->exists( $key ) ) {
294 $this->logger->warning(
295 __METHOD__ .
": Key \"$key\" deleted in Session and changed in \$_SESSION!"
297 $session->set( $key, $value );
299 } elseif ( $cache[$key] === $session->get( $key ) ) {
301 $session->set( $key, $value );
305 $this->logger->warning(
306 __METHOD__ .
": Key \"$key\" changed in both Session and \$_SESSION!"
312 \Wikimedia\PhpSessionSerializer::setLogger(
new NullLogger() );
313 foreach ( $cache as $key => $value ) {
314 if ( !array_key_exists( $key, $data ) && $session->exists( $key ) &&
315 \
Wikimedia\PhpSessionSerializer::encode( [ $key =>
true ] )
317 if ( $value === $session->get( $key ) ) {
319 $session->remove( $key );
323 $this->logger->warning(
324 __METHOD__ .
": Key \"$key\" changed in Session and deleted in \$_SESSION!"
329 \Wikimedia\PhpSessionSerializer::setLogger( $this->logger );
335 $this->logger->warning(
'Something wrote to $_SESSION!' );
339 $this->sessionFieldCache[$id] = iterator_to_array( $session );
353 #[\ReturnTypeWillChange]
355 if ( self::$instance !== $this ) {
356 throw new \UnexpectedValueException( __METHOD__ .
': Wrong instance called!' );
358 if ( !$this->enable ) {
359 throw new \BadMethodCallException(
'Attempt to use PHP session management' );
361 $session = $this->manager->getSessionById( $id,
false );
375 #[\ReturnTypeWillChange]
376 public function gc( $maxlifetime ) {
377 if ( self::$instance !== $this ) {
378 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.
Class representing a cache/ephemeral data store.
A class containing constants representing the names of configuration variables.
const PHPSessionHandling
Name constant for the PHPSessionHandling setting, for use with Config::get()