*/
public function getSession() {
if ( $this->sessionId !== null ) {
- return SessionManager::singleton()->getSessionById( (string)$this->sessionId, false, $this );
+ $session = SessionManager::singleton()->getSessionById( (string)$this->sessionId, true, $this );
+ if ( $session ) {
+ return $session;
+ }
}
$session = SessionManager::singleton()->getSessionForRequest( $this );
// Get new session, if applicable
$session = null;
if ( strlen( $params['sessionId'] ) ) { // don't make a new random ID
- $session = MediaWiki\Session\SessionManager::singleton()
- ->getSessionById( $params['sessionId'] );
+ $manager = MediaWiki\Session\SessionManager::singleton();
+ $session = $manager->getSessionById( $params['sessionId'], true )
+ ?: $manager->getEmptySession();
}
// Remove any user IP or agent information, and attach the request
* Store a result in the session data. Note that the caller is responsible
* for appropriate session_start and session_write_close calls.
*
- * @param MediaWiki\\Session\\Session $session Session to store result into
+ * @param MediaWiki\\Session\\Session|null $session Session to store result into
* @param string $result The result (Success|Warning|Failure)
* @param string $dataKey The key of the extra data
* @param mixed $dataValue The extra data itself
*/
protected function storeResultInSession(
- MediaWiki\Session\Session $session, $result, $dataKey, $dataValue
+ MediaWiki\Session\Session $session = null, $result, $dataKey, $dataValue
) {
- $data = self::getSessionData( $session, $this->params['sessionKey'] );
- $data['result'] = $result;
- $data[$dataKey] = $dataValue;
- self::setSessionData( $session, $this->params['sessionKey'], $data );
+ if ( $session ) {
+ $data = self::getSessionData( $session, $this->params['sessionKey'] );
+ $data['result'] = $result;
+ $data[$dataKey] = $dataValue;
+ self::setSessionData( $session, $this->params['sessionKey'], $data );
+ } else {
+ wfDebug( __METHOD__ . ': Cannot store result in session, session does not exist' );
+ }
}
/**
throw new \BadMethodCallException( 'Attempt to use PHP session management' );
}
- $session = $this->manager->getSessionById( $id, true );
+ $session = $this->manager->getSessionById( $id, false );
if ( !$session ) {
return '';
}
throw new \BadMethodCallException( 'Attempt to use PHP session management' );
}
- $session = $this->manager->getSessionById( $id );
+ $session = $this->manager->getSessionById( $id, true );
+ if ( !$session ) {
+ $this->logger->warning(
+ __METHOD__ . ": Session \"$id\" cannot be loaded, skipping write."
+ );
+ return false;
+ }
// First, decode the string PHP handed us
$data = \Wikimedia\PhpSessionSerializer::decode( $dataStr );
if ( !$this->enable ) {
throw new \BadMethodCallException( 'Attempt to use PHP session management' );
}
- $session = $this->manager->getSessionById( $id, true );
+ $session = $this->manager->getSessionById( $id, false );
if ( $session ) {
$session->clear();
}
// Someone used session_id(), so we need to follow suit.
// Note this overwrites whatever session might already be
// associated with $request with the one for $id.
- self::$globalSession = self::singleton()->getSessionById( $id, false, $request );
+ self::$globalSession = self::singleton()->getSessionById( $id, true, $request )
+ ?: $request->getSession();
}
}
return self::$globalSession;
return $session;
}
- public function getSessionById( $id, $noEmpty = false, WebRequest $request = null ) {
+ public function getSessionById( $id, $create = false, WebRequest $request = null ) {
if ( !self::validateSessionId( $id ) ) {
throw new \InvalidArgumentException( 'Invalid session ID' );
}
}
}
- if ( !$noEmpty && $session === null ) {
+ if ( $create && $session === null ) {
$ex = null;
try {
$session = $this->getEmptySessionInternal( $request, $id );
$ex->getMessage() );
$session = null;
}
- if ( $session === null ) {
- throw new \UnexpectedValueException(
- 'Can neither load the session nor create an empty session', 0, $ex
- );
- }
}
return $session;
* @return bool Whether the session info matches the stored data (if any)
*/
private function loadSessionInfoFromStore( SessionInfo &$info, WebRequest $request ) {
- $blob = $this->store->get( wfMemcKey( 'MWSession', $info->getId() ) );
+ $key = wfMemcKey( 'MWSession', $info->getId() );
+ $blob = $this->store->get( $key );
$newParams = array();
// Sanity check: blob must be an array, if it's saved at all
if ( !is_array( $blob ) ) {
$this->logger->warning( "Session $info: Bad data" );
+ $this->store->delete( $key );
return false;
}
!isset( $blob['metadata'] ) || !is_array( $blob['metadata'] )
) {
$this->logger->warning( "Session $info: Bad data structure" );
+ $this->store->delete( $key );
return false;
}
!array_key_exists( 'provider', $metadata )
) {
$this->logger->warning( "Session $info: Bad metadata" );
+ $this->store->delete( $key );
return false;
}
$newParams['provider'] = $provider = $this->getProvider( $metadata['provider'] );
if ( !$provider ) {
$this->logger->warning( "Session $info: Unknown provider, " . $metadata['provider'] );
+ $this->store->delete( $key );
return false;
}
} elseif ( $metadata['provider'] !== (string)$provider ) {
/**
* Fetch a session by ID
* @param string $id
- * @param bool $noEmpty Don't return an empty session
+ * @param bool $create If no session exists for $id, try to create a new one.
+ * May still return null if a session for $id exists but cannot be loaded.
* @param WebRequest|null $request Corresponding request. Any existing
* session associated with this WebRequest object will be overwritten.
* @return Session|null
*/
- public function getSessionById( $id, $noEmpty = false, WebRequest $request = null );
+ public function getSessionById( $id, $create = false, WebRequest $request = null );
/**
* Fetch a new, empty session
42 => 'forty-two',
'forty-two' => 42,
), iterator_to_array( $session ) );
+
+ // Test that write doesn't break if the session is invalid
+ $session = $manager->getEmptySession();
+ $session->persist();
+ session_id( $session->getId() );
+ session_start();
+ $this->mergeMwGlobalArrayValue( 'wgHooks', array(
+ 'SessionCheckInfo' => array( function ( &$reason ) {
+ $reason = 'Testing';
+ return false;
+ } ),
+ ) );
+ $this->assertNull( $manager->getSessionById( $session->getId(), true ), 'sanity check' );
+ session_write_close();
+ $this->mergeMwGlobalArrayValue( 'wgHooks', array(
+ 'SessionCheckInfo' => array(),
+ ) );
+ $this->assertNotNull( $manager->getSessionById( $session->getId(), true ), 'sanity check' );
}
public static function provideHandlers() {
// Unknown session ID
$id = $manager->generateSessionId();
- $session = $manager->getSessionById( $id );
+ $session = $manager->getSessionById( $id, true );
$this->assertInstanceOf( 'MediaWiki\\Session\\Session', $session );
$this->assertSame( $id, $session->getId() );
$id = $manager->generateSessionId();
- $this->assertNull( $manager->getSessionById( $id, true ) );
+ $this->assertNull( $manager->getSessionById( $id, false ) );
// Known but unloadable session ID
$this->logger->setCollect( true );
$id = $manager->generateSessionId();
- $this->store->setRawSession( $id, array( 'metadata' => array(
- 'provider' => 'DummySessionProvider',
- 'userId' => 0,
- 'userName' => null,
- 'userToken' => null,
+ $this->store->setSession( $id, array( 'metadata' => array(
+ 'userId' => User::idFromName( 'UTSysop' ),
+ 'userToken' => 'bad',
) ) );
- try {
- $manager->getSessionById( $id );
- $this->fail( 'Expected exception not thrown' );
- } catch ( \UnexpectedValueException $ex ) {
- $this->assertSame(
- 'Can neither load the session nor create an empty session',
- $ex->getMessage()
- );
- }
-
$this->assertNull( $manager->getSessionById( $id, true ) );
+ $this->assertNull( $manager->getSessionById( $id, false ) );
$this->logger->setCollect( false );
// Known session ID
$this->store->setSession( $id, array() );
- $session = $manager->getSessionById( $id );
+ $session = $manager->getSessionById( $id, false );
$this->assertInstanceOf( 'MediaWiki\\Session\\Session', $session );
$this->assertSame( $id, $session->getId() );
}
$sessionId = $session->getSessionId();
$id = (string)$sessionId;
- $this->assertSame( $sessionId, $manager->getSessionById( $id )->getSessionId() );
+ $this->assertSame( $sessionId, $manager->getSessionById( $id, true )->getSessionId() );
$manager->changeBackendId( $backend );
$this->assertSame( $sessionId, $session->getSessionId() );
$this->assertNotEquals( $id, (string)$sessionId );
$id = (string)$sessionId;
- $this->assertSame( $sessionId, $manager->getSessionById( $id )->getSessionId() );
+ $this->assertSame( $sessionId, $manager->getSessionById( $id, true )->getSessionId() );
// Destruction of the session here causes the backend to be deregistered
$session = null;
);
}
- $session = $manager->getSessionById( $id );
+ $session = $manager->getSessionById( $id, true );
$this->assertSame( $sessionId, $session->getSessionId() );
}