}
}
+ /**
+ * Get the error message as HTML. This is done by parsing the wikitext error
+ * message.
+ */
+ public function getHTML( $shortContext = false, $longContext = false ) {
+ $text = $this->getWikiText( $shortContext, $longContext );
+ return MessageCache::singleton()->transform( $text, true );
+ }
+
/**
* Return an array with the wikitext for each item in the array.
* @param $errors Array
}
/**
- * Add this existing user object to the database
+ * Add this existing user object to the database. If the user already
+ * exists, a fatal status object is returned, and the user object is
+ * initialised with the data from the database.
+ *
+ * Previously, this function generated a DB error due to a key conflict
+ * if the user already existed. Many extension callers use this function
+ * in code along the lines of:
+ *
+ * $user = User::newFromName( $name );
+ * if ( !$user->isLoggedIn() ) {
+ * $user->addToDatabase();
+ * }
+ * // do something with $user...
+ *
+ * However, this was vulnerable to a race condition (bug 16020). By
+ * initialising the user object if the user exists, we aim to support this
+ * calling sequence as far as possible.
+ *
+ * Note that if the user exists, this function will acquire a write lock,
+ * so it is still advisable to make the call conditional on isLoggedIn(),
+ * and to commit the transaction after calling.
+ *
+ * @return Status
*/
public function addToDatabase() {
$this->load();
'user_registration' => $dbw->timestamp( $this->mRegistration ),
'user_editcount' => 0,
'user_touched' => $dbw->timestamp( $this->mTouched ),
- ), __METHOD__
+ ), __METHOD__,
+ array( 'IGNORE' )
);
+ if ( !$dbw->affectedRows() ) {
+ $this->mId = $dbw->selectField( 'user', 'user_id',
+ array( 'user_name' => $this->mName ), __METHOD__ );
+ $loaded = false;
+ if ( $this->mId ) {
+ if ( $this->loadFromDatabase() ) {
+ $loaded = true;
+ }
+ }
+ if ( !$loaded ) {
+ throw new MWException( __METHOD__. ": hit a key conflict attempting " .
+ "to insert a user row, but then it doesn't exist when we select it!" );
+ }
+ return Status::newFatal( 'userexists' );
+ }
$this->mId = $dbw->insertId();
// Clear instance cache other than user table data, which is already accurate
$this->clearInstanceCache();
$this->saveOptions();
+ return Status::newGood();
}
/**
}
self::clearCreateaccountToken();
- return $this->initUser( $u, false );
+
+ $status = $this->initUser( $u, false );
+ if ( !$status->isOK() ) {
+ $this->mainLoginForm( $status->getHTML() );
+ return false;
+ }
+ return $status->value;
}
/**
*
* @param $u User object.
* @param $autocreate boolean -- true if this is an autocreation via auth plugin
- * @return User object.
+ * @return Status object, with the User object in the value member on success
* @private
*/
function initUser( $u, $autocreate ) {
global $wgAuth;
- $u->addToDatabase();
+ $status = $u->addToDatabase();
+ if ( !$status->isOK() ) {
+ return $status;
+ }
if ( $wgAuth->allowPasswordChange() ) {
$u->setPassword( $this->mPassword );
# Update user count
DeferredUpdates::addUpdate( new SiteStatsUpdate( 0, 0, 0, 0, 1 ) );
- return $u;
+ return Status::newGood( $u );
}
/**
}
wfDebug( __METHOD__ . ": creating account\n" );
- $this->initUser( $user, true );
+ $status = $this->initUser( $user, true );
+
+ if ( !$status->isOK() ) {
+ $errors = $status->getErrorsByType( 'error' );
+ $this->mAbortLoginErrorMsg = $errors[0]['message'];
+ return self::ABORTED;
+ }
+
return self::SUCCESS;
}