summaryrefslogtreecommitdiff
path: root/includes/User.php
diff options
context:
space:
mode:
Diffstat (limited to 'includes/User.php')
-rw-r--r--includes/User.php326
1 files changed, 218 insertions, 108 deletions
diff --git a/includes/User.php b/includes/User.php
index 1529da1e..0a3db4c0 100644
--- a/includes/User.php
+++ b/includes/User.php
@@ -66,6 +66,11 @@ class User {
const EDIT_TOKEN_SUFFIX = EDIT_TOKEN_SUFFIX;
/**
+ * Maximum items in $mWatchedItems
+ */
+ const MAX_WATCHED_ITEMS_CACHE = 100;
+
+ /**
* Array of Strings List of member variables which are saved to the
* shared cache (memcached). Any operation which changes the
* corresponding database fields must call a cache-clearing function.
@@ -114,9 +119,11 @@ class User {
'delete',
'deletedhistory',
'deletedtext',
+ 'deletelogentry',
'deleterevision',
'edit',
'editinterface',
+ 'editprotected',
'editusercssjs', #deprecated
'editusercss',
'edituserjs',
@@ -134,12 +141,15 @@ class User {
'nominornewtalk',
'noratelimit',
'override-export-depth',
+ 'passwordreset',
'patrol',
+ 'patrolmarks',
'protect',
'proxyunbannable',
'purge',
'read',
'reupload',
+ 'reupload-own',
'reupload-shared',
'rollback',
'sendemail',
@@ -165,8 +175,8 @@ class User {
//@{
var $mId, $mName, $mRealName, $mPassword, $mNewpassword, $mNewpassTime,
$mEmail, $mTouched, $mToken, $mEmailAuthenticated,
- $mEmailToken, $mEmailTokenExpires, $mRegistration, $mGroups, $mOptionOverrides,
- $mCookiePassword, $mEditCount, $mAllowUsertalk;
+ $mEmailToken, $mEmailTokenExpires, $mRegistration, $mEditCount,
+ $mGroups, $mOptionOverrides;
//@}
/**
@@ -210,10 +220,20 @@ class User {
var $mBlock;
/**
+ * @var bool
+ */
+ var $mAllowUsertalk;
+
+ /**
* @var Block
*/
private $mBlockedFromCreateAccount = false;
+ /**
+ * @var Array
+ */
+ private $mWatchedItems = array();
+
static $idCacheByName = array();
/**
@@ -445,22 +465,20 @@ class User {
/**
* Get the username corresponding to a given user ID
* @param $id Int User ID
- * @return String|false The corresponding username
+ * @return String|bool The corresponding username
*/
public static function whoIs( $id ) {
- $dbr = wfGetDB( DB_SLAVE );
- return $dbr->selectField( 'user', 'user_name', array( 'user_id' => $id ), __METHOD__ );
+ return UserCache::singleton()->getProp( $id, 'name' );
}
/**
* Get the real name of a user given their user ID
*
* @param $id Int User ID
- * @return String|false The corresponding user's real name
+ * @return String|bool The corresponding user's real name
*/
public static function whoIsReal( $id ) {
- $dbr = wfGetDB( DB_SLAVE );
- return $dbr->selectField( 'user', 'user_real_name', array( 'user_id' => $id ), __METHOD__ );
+ return UserCache::singleton()->getProp( $id, 'real_name' );
}
/**
@@ -512,7 +530,7 @@ class User {
* as 300.300.300.300 will return true because it looks like an IP
* address, despite not being strictly valid.
*
- * We match \d{1,3}\.\d{1,3}\.\d{1,3}\.xxx as an anonymous IP
+ * We match "\d{1,3}\.\d{1,3}\.\d{1,3}\.xxx" as an anonymous IP
* address because the usemod software would "cloak" anonymous IP
* addresses like this, if we allowed accounts like this to be created
* new users could get the old edits of these anonymous users.
@@ -606,7 +624,7 @@ class User {
// Certain names may be reserved for batch processes.
foreach ( $reservedUsernames as $reserved ) {
if ( substr( $reserved, 0, 4 ) == 'msg:' ) {
- $reserved = wfMsgForContent( substr( $reserved, 4 ) );
+ $reserved = wfMessage( substr( $reserved, 4 ) )->inContentLanguage()->text();
}
if ( $reserved == $name ) {
return false;
@@ -1023,7 +1041,7 @@ class User {
}
$dbr = wfGetDB( DB_MASTER );
- $s = $dbr->selectRow( 'user', '*', array( 'user_id' => $this->mId ), __METHOD__ );
+ $s = $dbr->selectRow( 'user', self::selectFields(), array( 'user_id' => $this->mId ), __METHOD__ );
wfRunHooks( 'UserLoadFromDatabase', array( $this, &$s ) );
@@ -1278,22 +1296,22 @@ class User {
}
# User/IP blocking
- $block = Block::newFromTarget( $this->getName(), $ip, !$bFromSlave );
+ $block = Block::newFromTarget( $this, $ip, !$bFromSlave );
# Proxy blocking
if ( !$block instanceof Block && $ip !== null && !$this->isAllowed( 'proxyunbannable' )
- && !in_array( $ip, $wgProxyWhitelist ) )
+ && !in_array( $ip, $wgProxyWhitelist ) )
{
# Local list
if ( self::isLocallyBlockedProxy( $ip ) ) {
$block = new Block;
- $block->setBlocker( wfMsg( 'proxyblocker' ) );
- $block->mReason = wfMsg( 'proxyblockreason' );
+ $block->setBlocker( wfMessage( 'proxyblocker' )->text() );
+ $block->mReason = wfMessage( 'proxyblockreason' )->text();
$block->setTarget( $ip );
} elseif ( $this->isAnon() && $this->isDnsBlacklisted( $ip ) ) {
$block = new Block;
- $block->setBlocker( wfMsg( 'sorbs' ) );
- $block->mReason = wfMsg( 'sorbsreason' );
+ $block->setBlocker( wfMessage( 'sorbs' )->text() );
+ $block->mReason = wfMessage( 'sorbsreason' )->text();
$block->setTarget( $ip );
}
}
@@ -1372,11 +1390,11 @@ class User {
$ipList = gethostbynamel( $host );
if( $ipList ) {
- wfDebug( "Hostname $host is {$ipList[0]}, it's a proxy says $base!\n" );
+ wfDebugLog( 'dnsblacklist', "Hostname $host is {$ipList[0]}, it's a proxy says $base!\n" );
$found = true;
break;
} else {
- wfDebug( "Requested $host, not found in $base.\n" );
+ wfDebugLog( 'dnsblacklist', "Requested $host, not found in $base.\n" );
}
}
}
@@ -1512,7 +1530,7 @@ class User {
$count = $wgMemc->get( $key );
// Already pinged?
if( $count ) {
- if( $count > $max ) {
+ if( $count >= $max ) {
wfDebug( __METHOD__ . ": tripped! $key at $count $summary\n" );
if( $wgRateLimitLog ) {
wfSuppressWarnings();
@@ -1748,16 +1766,22 @@ class User {
# Check memcached separately for anons, who have no
# entire User object stored in there.
if( !$this->mId ) {
- global $wgMemc;
- $key = wfMemcKey( 'newtalk', 'ip', $this->getName() );
- $newtalk = $wgMemc->get( $key );
- if( strval( $newtalk ) !== '' ) {
- $this->mNewtalk = (bool)$newtalk;
+ global $wgDisableAnonTalk;
+ if( $wgDisableAnonTalk ) {
+ // Anon newtalk disabled by configuration.
+ $this->mNewtalk = false;
} else {
- // Since we are caching this, make sure it is up to date by getting it
- // from the master
- $this->mNewtalk = $this->checkNewtalk( 'user_ip', $this->getName(), true );
- $wgMemc->set( $key, (int)$this->mNewtalk, 1800 );
+ global $wgMemc;
+ $key = wfMemcKey( 'newtalk', 'ip', $this->getName() );
+ $newtalk = $wgMemc->get( $key );
+ if( strval( $newtalk ) !== '' ) {
+ $this->mNewtalk = (bool)$newtalk;
+ } else {
+ // Since we are caching this, make sure it is up to date by getting it
+ // from the master
+ $this->mNewtalk = $this->checkNewtalk( 'user_ip', $this->getName(), true );
+ $wgMemc->set( $key, (int)$this->mNewtalk, 1800 );
+ }
}
} else {
$this->mNewtalk = $this->checkNewtalk( 'user_id', $this->mId );
@@ -1773,14 +1797,20 @@ class User {
*/
public function getNewMessageLinks() {
$talks = array();
- if( !wfRunHooks( 'UserRetrieveNewTalks', array( &$this, &$talks ) ) )
+ if( !wfRunHooks( 'UserRetrieveNewTalks', array( &$this, &$talks ) ) ) {
return $talks;
-
- if( !$this->getNewtalk() )
+ } elseif( !$this->getNewtalk() ) {
return array();
- $up = $this->getUserPage();
- $utp = $up->getTalkPage();
- return array( array( 'wiki' => wfWikiID(), 'link' => $utp->getLocalURL() ) );
+ }
+ $utp = $this->getTalkPage();
+ $dbr = wfGetDB( DB_SLAVE );
+ // Get the "last viewed rev" timestamp from the oldest message notification
+ $timestamp = $dbr->selectField( 'user_newtalk',
+ 'MIN(user_last_timestamp)',
+ $this->isAnon() ? array( 'user_ip' => $this->getName() ) : array( 'user_id' => $this->getID() ),
+ __METHOD__ );
+ $rev = $timestamp ? Revision::loadFromTimestamp( $dbr, $utp, $timestamp ) : null;
+ return array( array( 'wiki' => wfWikiID(), 'link' => $utp->getLocalURL(), 'rev' => $rev ) );
}
/**
@@ -1807,12 +1837,17 @@ class User {
* Add or update the new messages flag
* @param $field String 'user_ip' for anonymous users, 'user_id' otherwise
* @param $id String|Int User's IP address for anonymous users, User ID otherwise
+ * @param $curRev Revision new, as yet unseen revision of the user talk page. Ignored if null.
* @return Bool True if successful, false otherwise
*/
- protected function updateNewtalk( $field, $id ) {
+ protected function updateNewtalk( $field, $id, $curRev = null ) {
+ // Get timestamp of the talk page revision prior to the current one
+ $prevRev = $curRev ? $curRev->getPrevious() : false;
+ $ts = $prevRev ? $prevRev->getTimestamp() : null;
+ // Mark the user as having new messages since this revision
$dbw = wfGetDB( DB_MASTER );
$dbw->insert( 'user_newtalk',
- array( $field => $id ),
+ array( $field => $id, 'user_last_timestamp' => $dbw->timestampOrNull( $ts ) ),
__METHOD__,
'IGNORE' );
if ( $dbw->affectedRows() ) {
@@ -1847,8 +1882,9 @@ class User {
/**
* Update the 'You have new messages!' status.
* @param $val Bool Whether the user has new messages
+ * @param $curRev Revision new, as yet unseen revision of the user talk page. Ignored if null or !$val.
*/
- public function setNewtalk( $val ) {
+ public function setNewtalk( $val, $curRev = null ) {
if( wfReadOnly() ) {
return;
}
@@ -1866,7 +1902,7 @@ class User {
global $wgMemc;
if( $val ) {
- $changed = $this->updateNewtalk( $field, $id );
+ $changed = $this->updateNewtalk( $field, $id, $curRev );
} else {
$changed = $this->deleteNewtalk( $field, $id );
}
@@ -1921,10 +1957,19 @@ class User {
$this->mTouched = self::newTouchedTimestamp();
$dbw = wfGetDB( DB_MASTER );
- $dbw->update( 'user',
- array( 'user_touched' => $dbw->timestamp( $this->mTouched ) ),
- array( 'user_id' => $this->mId ),
- __METHOD__ );
+
+ // Prevent contention slams by checking user_touched first
+ $now = $dbw->timestamp( $this->mTouched );
+ $needsPurge = $dbw->selectField( 'user', '1',
+ array( 'user_id' => $this->mId, 'user_touched < ' . $dbw->addQuotes( $now ) )
+ );
+ if ( $needsPurge ) {
+ $dbw->update( 'user',
+ array( 'user_touched' => $now ),
+ array( 'user_id' => $this->mId, 'user_touched < ' . $dbw->addQuotes( $now ) ),
+ __METHOD__
+ );
+ }
$this->clearSharedCache();
}
@@ -1971,7 +2016,7 @@ class User {
if( $str !== null ) {
if( !$wgAuth->allowPasswordChange() ) {
- throw new PasswordError( wfMsg( 'password-change-forbidden' ) );
+ throw new PasswordError( wfMessage( 'password-change-forbidden' )->text() );
}
if( !$this->isValidPassword( $str ) ) {
@@ -1984,12 +2029,12 @@ class User {
$message = $valid;
$params = array( $wgMinimalPasswordLength );
}
- throw new PasswordError( wfMsgExt( $message, array( 'parsemag' ), $params ) );
+ throw new PasswordError( wfMessage( $message, $params )->text() );
}
}
if( !$wgAuth->setPassword( $this, $str ) ) {
- throw new PasswordError( wfMsg( 'externaldberror' ) );
+ throw new PasswordError( wfMessage( 'externaldberror' )->text() );
}
$this->setInternalPassword( $str );
@@ -2036,7 +2081,6 @@ class User {
* @param $token String|bool If specified, set the token to this value
*/
public function setToken( $token = false ) {
- global $wgSecretKey, $wgProxyKey;
$this->load();
if ( !$token ) {
$this->mToken = MWCryptRand::generateHex( USER_TOKEN_LENGTH );
@@ -2046,16 +2090,6 @@ class User {
}
/**
- * Set the cookie password
- *
- * @param $str String New cookie password
- */
- private function setCookiePassword( $str ) {
- $this->load();
- $this->mCookiePassword = md5( $str );
- }
-
- /**
* Set the password for a password reminder or new account email
*
* @param $str String New password to set
@@ -2119,6 +2153,42 @@ class User {
}
/**
+ * Set the user's e-mail address and a confirmation mail if needed.
+ *
+ * @since 1.20
+ * @param $str String New e-mail address
+ * @return Status
+ */
+ public function setEmailWithConfirmation( $str ) {
+ global $wgEnableEmail, $wgEmailAuthentication;
+
+ if ( !$wgEnableEmail ) {
+ return Status::newFatal( 'emaildisabled' );
+ }
+
+ $oldaddr = $this->getEmail();
+ if ( $str === $oldaddr ) {
+ return Status::newGood( true );
+ }
+
+ $this->setEmail( $str );
+
+ if ( $str !== '' && $wgEmailAuthentication ) {
+ # Send a confirmation request to the new address if needed
+ $type = $oldaddr != '' ? 'changed' : 'set';
+ $result = $this->sendConfirmationMail( $type );
+ if ( $result->isGood() ) {
+ # Say the the caller that a confirmation mail has been sent
+ $result->value = 'eauth';
+ }
+ } else {
+ $result = Status::newGood( true );
+ }
+
+ return $result;
+ }
+
+ /**
* Get the user's real name
* @return String User's real name
*/
@@ -2239,9 +2309,11 @@ class User {
$this->loadOptions();
// Explicitly NULL values should refer to defaults
- global $wgDefaultUserOptions;
- if( is_null( $val ) && isset( $wgDefaultUserOptions[$oname] ) ) {
- $val = $wgDefaultUserOptions[$oname];
+ if( is_null( $val ) ) {
+ $defaultOption = self::getDefaultOption( $oname );
+ if( !is_null( $defaultOption ) ) {
+ $val = $defaultOption;
+ }
}
$this->mOptions[$oname] = $val;
@@ -2251,7 +2323,10 @@ class User {
* Reset all options to the site defaults
*/
public function resetOptions() {
+ $this->load();
+
$this->mOptions = self::getDefaultOptions();
+ $this->mOptionsLoaded = true;
}
/**
@@ -2572,13 +2647,33 @@ class User {
}
/**
+ * Get a WatchedItem for this user and $title.
+ *
+ * @param $title Title
+ * @return WatchedItem
+ */
+ public function getWatchedItem( $title ) {
+ $key = $title->getNamespace() . ':' . $title->getDBkey();
+
+ if ( isset( $this->mWatchedItems[$key] ) ) {
+ return $this->mWatchedItems[$key];
+ }
+
+ if ( count( $this->mWatchedItems ) >= self::MAX_WATCHED_ITEMS_CACHE ) {
+ $this->mWatchedItems = array();
+ }
+
+ $this->mWatchedItems[$key] = WatchedItem::fromUserTitle( $this, $title );
+ return $this->mWatchedItems[$key];
+ }
+
+ /**
* Check the watched status of an article.
* @param $title Title of the article to look at
* @return Bool
*/
public function isWatched( $title ) {
- $wl = WatchedItem::fromUserTitle( $this, $title );
- return $wl->isWatched();
+ return $this->getWatchedItem( $title )->isWatched();
}
/**
@@ -2586,8 +2681,7 @@ class User {
* @param $title Title of the article to look at
*/
public function addWatch( $title ) {
- $wl = WatchedItem::fromUserTitle( $this, $title );
- $wl->addWatch();
+ $this->getWatchedItem( $title )->addWatch();
$this->invalidateCache();
}
@@ -2596,8 +2690,7 @@ class User {
* @param $title Title of the article to look at
*/
public function removeWatch( $title ) {
- $wl = WatchedItem::fromUserTitle( $this, $title );
- $wl->removeWatch();
+ $this->getWatchedItem( $title )->removeWatch();
$this->invalidateCache();
}
@@ -2635,28 +2728,14 @@ class User {
// The query to find out if it is watched is cached both in memcached and per-invocation,
// and when it does have to be executed, it can be on a slave
// If this is the user's newtalk page, we always update the timestamp
- if( $title->getNamespace() == NS_USER_TALK &&
+ $force = '';
+ if ( $title->getNamespace() == NS_USER_TALK &&
$title->getText() == $this->getName() )
{
- $watched = true;
- } else {
- $watched = $this->isWatched( $title );
+ $force = 'force';
}
- // If the page is watched by the user (or may be watched), update the timestamp on any
- // any matching rows
- if ( $watched ) {
- $dbw = wfGetDB( DB_MASTER );
- $dbw->update( 'watchlist',
- array( /* SET */
- 'wl_notificationtimestamp' => null
- ), array( /* WHERE */
- 'wl_title' => $title->getDBkey(),
- 'wl_namespace' => $title->getNamespace(),
- 'wl_user' => $this->getID()
- ), __METHOD__
- );
- }
+ $this->getWatchedItem( $title )->resetNotificationTimestamp( $force );
}
/**
@@ -2903,6 +2982,7 @@ class User {
'user_token' => strval( $user->mToken ),
'user_registration' => $dbw->timestamp( $user->mRegistration ),
'user_editcount' => 0,
+ 'user_touched' => $dbw->timestamp( self::newTouchedTimestamp() ),
);
foreach ( $params as $name => $value ) {
$fields["user_$name"] = $value;
@@ -2921,6 +3001,9 @@ class User {
*/
public function addToDatabase() {
$this->load();
+
+ $this->mTouched = self::newTouchedTimestamp();
+
$dbw = wfGetDB( DB_MASTER );
$seqVal = $dbw->nextSequenceValue( 'user_user_id_seq' );
$dbw->insert( 'user',
@@ -2936,6 +3019,7 @@ class User {
'user_token' => strval( $this->mToken ),
'user_registration' => $dbw->timestamp( $this->mRegistration ),
'user_editcount' => 0,
+ 'user_touched' => $dbw->timestamp( $this->mTouched ),
), __METHOD__
);
$this->mId = $dbw->insertId();
@@ -2994,7 +3078,7 @@ class User {
*/
public function getPageRenderingHash() {
wfDeprecated( __METHOD__, '1.17' );
-
+
global $wgUseDynamicDates, $wgRenderHashAppend, $wgLang, $wgContLang;
if( $this->mHash ){
return $this->mHash;
@@ -3212,6 +3296,7 @@ class User {
*
* @param $salt String Optional salt value
* @return String The new random token
+ * @deprecated since 1.20; Use MWCryptRand for secure purposes or wfRandomString for pesudo-randomness
*/
public static function generateToken( $salt = '' ) {
return MWCryptRand::generateHex( 32 );
@@ -3273,15 +3358,15 @@ class User {
$message = 'confirmemail_body_' . $type;
}
- return $this->sendMail( wfMsg( 'confirmemail_subject' ),
- wfMsg( $message,
+ return $this->sendMail( wfMessage( 'confirmemail_subject' )->text(),
+ wfMessage( $message,
$this->getRequest()->getIP(),
$this->getName(),
$url,
$wgLang->timeanddate( $expiration, false ),
$invalidateURL,
$wgLang->date( $expiration, false ),
- $wgLang->time( $expiration, false ) ) );
+ $wgLang->time( $expiration, false ) )->text() );
}
/**
@@ -3344,7 +3429,7 @@ class User {
* @return String New token URL
*/
private function invalidationTokenUrl( $token ) {
- return $this->getTokenUrl( 'Invalidateemail', $token );
+ return $this->getTokenUrl( 'InvalidateEmail', $token );
}
/**
@@ -3372,7 +3457,7 @@ class User {
*
* @note Call saveSettings() after calling this function to commit the change.
*
- * @return true
+ * @return bool
*/
public function confirmEmail() {
$this->setEmailAuthenticationTimestamp( wfTimestampNow() );
@@ -3385,7 +3470,7 @@ class User {
* address if it was already confirmed.
*
* @note Call saveSettings() after calling this function to commit the change.
- * @return true
+ * @return bool Returns true
*/
function invalidateEmail() {
$this->load();
@@ -3933,10 +4018,10 @@ class User {
$action = 'create2';
if ( $byEmail ) {
if ( $reason === '' ) {
- $reason = wfMsgForContent( 'newuserlog-byemail' );
+ $reason = wfMessage( 'newuserlog-byemail' )->inContentLanguage()->text();
} else {
$reason = $wgContLang->commaList( array(
- $reason, wfMsgForContent( 'newuserlog-byemail' ) ) );
+ $reason, wfMessage( 'newuserlog-byemail' )->inContentLanguage()->text() ) );
}
}
}
@@ -3953,7 +4038,7 @@ class User {
* Add an autocreate newuser log entry for this user
* Used by things like CentralAuth and perhaps other authplugins.
*
- * @return true
+ * @return bool
*/
public function addNewUserLogEntryAutoCreate() {
global $wgNewUserLog;
@@ -3961,7 +4046,7 @@ class User {
return true; // disabled
}
$log = new LogPage( 'newusers', false );
- $log->addEntry( 'autocreate', $this->getUserPage(), '', array( $this->getId() ) );
+ $log->addEntry( 'autocreate', $this->getUserPage(), '', array( $this->getId() ), $this );
return true;
}
@@ -3988,7 +4073,7 @@ class User {
$res = $dbr->select(
'user_properties',
- '*',
+ array( 'up_property', 'up_value' ),
array( 'up_user' => $this->getId() ),
__METHOD__
);
@@ -4011,13 +4096,9 @@ class User {
protected function saveOptions() {
global $wgAllowPrefChange;
- $extuser = ExternalUser::newFromUser( $this );
-
$this->loadOptions();
- $dbw = wfGetDB( DB_MASTER );
-
- $insert_rows = array();
+ // Not using getOptions(), to keep hidden preferences in database
$saveOptions = $this->mOptions;
// Allow hooks to abort, for instance to save to a global profile.
@@ -4026,13 +4107,17 @@ class User {
return;
}
+ $extuser = ExternalUser::newFromUser( $this );
+ $userId = $this->getId();
+ $insert_rows = array();
foreach( $saveOptions as $key => $value ) {
# Don't bother storing default values
- if ( ( is_null( self::getDefaultOption( $key ) ) &&
- !( $value === false || is_null($value) ) ) ||
- $value != self::getDefaultOption( $key ) ) {
+ $defaultOption = self::getDefaultOption( $key );
+ if ( ( is_null( $defaultOption ) &&
+ !( $value === false || is_null( $value ) ) ) ||
+ $value != $defaultOption ) {
$insert_rows[] = array(
- 'up_user' => $this->getId(),
+ 'up_user' => $userId,
'up_property' => $key,
'up_value' => $value,
);
@@ -4049,7 +4134,8 @@ class User {
}
}
- $dbw->delete( 'user_properties', array( 'up_user' => $this->getId() ), __METHOD__ );
+ $dbw = wfGetDB( DB_MASTER );
+ $dbw->delete( 'user_properties', array( 'up_user' => $userId ), __METHOD__ );
$dbw->insert( 'user_properties', $insert_rows, __METHOD__ );
}
@@ -4104,11 +4190,35 @@ class User {
/*
if ( $wgMinimalPasswordLength > 1 ) {
$ret['pattern'] = '.{' . intval( $wgMinimalPasswordLength ) . ',}';
- $ret['title'] = wfMsgExt( 'passwordtooshort', 'parsemag',
- $wgMinimalPasswordLength );
+ $ret['title'] = wfMessage( 'passwordtooshort' )
+ ->numParams( $wgMinimalPasswordLength )->text();
}
*/
return $ret;
}
+
+ /**
+ * Return the list of user fields that should be selected to create
+ * a new user object.
+ * @return array
+ */
+ public static function selectFields() {
+ return array(
+ 'user_id',
+ 'user_name',
+ 'user_real_name',
+ 'user_password',
+ 'user_newpassword',
+ 'user_newpass_time',
+ 'user_email',
+ 'user_touched',
+ 'user_token',
+ 'user_email_authenticated',
+ 'user_email_token',
+ 'user_email_token_expires',
+ 'user_registration',
+ 'user_editcount',
+ );
+ }
}