28use Psr\Log\LoggerInterface;
29use Psr\Log\NullLogger;
30use SessionHandlerInterface;
31use Wikimedia\AtEase\AtEase;
33use Wikimedia\PhpSessionSerializer;
58 $this->setEnableFlags(
61 $manager->setupPHPSessionHandler( $this );
72 private function setEnableFlags( $PHPSessionHandling ) {
73 switch ( $PHPSessionHandling ) {
85 $this->enable =
false;
104 return self::$instance && self::$instance->enable;
111 if ( self::$instance ) {
112 $manager->setupPHPSessionHandler( 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 AtEase::suppressWarnings();
131 ini_set(
'session.use_cookies', 0 );
137 session_cache_limiter(
'' );
140 PhpSessionSerializer::setSerializeHandler();
144 session_set_save_handler( self::$instance,
true );
146 AtEase::restoreWarnings();
160 if ( $this->manager !==
$manager ) {
162 if ( $this->manager ) {
163 session_write_close();
168 PhpSessionSerializer::setLogger( $this->logger );
179 #[\ReturnTypeWillChange]
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' );
195 #[\ReturnTypeWillChange]
197 if ( self::$instance !== $this ) {
198 throw new \UnexpectedValueException( __METHOD__ .
': Wrong instance called!' );
200 $this->sessionFieldCache = [];
210 #[\ReturnTypeWillChange]
212 if ( self::$instance !== $this ) {
213 throw new \UnexpectedValueException( __METHOD__ .
': Wrong instance called!' );
215 if ( !$this->enable ) {
216 throw new \BadMethodCallException(
'Attempt to use PHP session management' );
219 $session = $this->manager->getSessionById( $id,
false );
225 $data = iterator_to_array( $session );
226 $this->sessionFieldCache[$id] = $data;
227 return (
string)PhpSessionSerializer::encode( $data );
239 #[\ReturnTypeWillChange]
240 public function write( $id, $dataStr ) {
241 if ( self::$instance !== $this ) {
242 throw new \UnexpectedValueException( __METHOD__ .
': Wrong instance called!' );
244 if ( !$this->enable ) {
245 throw new \BadMethodCallException(
'Attempt to use PHP session management' );
248 $session = $this->manager->getSessionById( $id,
true );
252 $this->logger->warning(
253 __METHOD__ .
': Session "{session}" cannot be loaded, skipping write.',
261 $data = PhpSessionSerializer::decode( $dataStr );
262 if ( $data ===
null ) {
270 $cache = $this->sessionFieldCache[$id] ?? [];
271 foreach ( $data as $key => $value ) {
272 if ( !array_key_exists( $key, $cache ) ) {
273 if ( $session->exists( $key ) ) {
275 $this->logger->warning(
276 __METHOD__ .
": Key \"$key\" added in both Session and \$_SESSION!"
280 $session->set( $key, $value );
283 } elseif ( $cache[$key] === $value ) {
285 } elseif ( !$session->exists( $key ) ) {
287 $this->logger->warning(
288 __METHOD__ .
": Key \"$key\" deleted in Session and changed in \$_SESSION!"
290 $session->set( $key, $value );
292 } elseif ( $cache[$key] === $session->get( $key ) ) {
294 $session->set( $key, $value );
298 $this->logger->warning(
299 __METHOD__ .
": Key \"$key\" changed in both Session and \$_SESSION!"
305 PhpSessionSerializer::setLogger(
new NullLogger() );
306 foreach ( $cache as $key => $value ) {
307 if ( !array_key_exists( $key, $data ) && $session->exists( $key ) &&
308 PhpSessionSerializer::encode( [ $key =>
true ] )
310 if ( $value === $session->get( $key ) ) {
312 $session->remove( $key );
316 $this->logger->warning(
317 __METHOD__ .
": Key \"$key\" changed in Session and deleted in \$_SESSION!"
322 PhpSessionSerializer::setLogger( $this->logger );
328 $this->logger->warning(
'Something wrote to $_SESSION!' );
332 $this->sessionFieldCache[$id] = iterator_to_array( $session );
346 #[\ReturnTypeWillChange]
348 if ( self::$instance !== $this ) {
349 throw new \UnexpectedValueException( __METHOD__ .
': Wrong instance called!' );
351 if ( !$this->enable ) {
352 throw new \BadMethodCallException(
'Attempt to use PHP session management' );
354 $session = $this->manager->getSessionById( $id,
false );
368 #[\ReturnTypeWillChange]
369 public function gc( $maxlifetime ) {
370 if ( self::$instance !== $this ) {
371 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()