* will be loaded once more from the database when accessing them.
*
* @param $row Array A row from the user table
+ * @param $data Array Further data to load into the object (see User::loadFromRow for valid keys)
* @return User
*/
- public static function newFromRow( $row ) {
+ public static function newFromRow( $row, $data = null ) {
$user = new User;
- $user->loadFromRow( $row );
+ $user->loadFromRow( $row, $data );
return $user;
}
* Initialize this object from a row from the user table.
*
* @param $row Array Row from the user table to load.
+ * @param $data Array Further user data to load into the object
+ *
+ * user_groups Array with groups out of the user_groups table
+ * user_properties Array with properties out of the user_properties table
*/
- public function loadFromRow( $row ) {
+ public function loadFromRow( $row, $data = null ) {
$all = true;
$this->mGroups = null; // deferred
if ( $all ) {
$this->mLoadedItems = true;
}
+
+ if ( is_array( $data ) ) {
+ if ( is_array( $data['user_groups'] ) ) {
+ $this->mGroups = $data['user_groups'];
+ }
+ if ( is_array( $data['user_properties'] ) ) {
+ $this->loadOptions( $data['user_properties'] );
+ }
+ }
}
/**
}
$newGroups = array_merge( $oldGroups, $toPromote ); // all groups
- $log = new LogPage( 'rights', $wgAutopromoteOnceLogInRC /* in RC? */ );
- $log->addEntry( 'autopromote',
- $this->getUserPage(),
- '', // no comment
- // These group names are "list to texted"-ed in class LogPage.
- array( implode( ', ', $oldGroups ), implode( ', ', $newGroups ) )
- );
+ $logEntry = new ManualLogEntry( 'rights', 'autopromote' );
+ $logEntry->setPerformer( $this );
+ $logEntry->setTarget( $this->getUserPage() );
+ $logEntry->setParameters( array(
+ '4::oldgroups' => $oldGroups,
+ '5::newgroups' => $newGroups,
+ ) );
+ $logid = $logEntry->insert();
+ if ( $wgAutopromoteOnceLogInRC ) {
+ $logEntry->publish( $logid );
+ }
}
}
return $toPromote;
public static function getDefaultOptions() {
global $wgNamespacesToBeSearchedDefault, $wgDefaultUserOptions, $wgContLang, $wgDefaultSkin;
+ static $defOpt = null;
+ if ( !defined( 'MW_PHPUNIT_TEST' ) && $defOpt !== null ) {
+ // Disabling this for the unit tests, as they rely on being able to change $wgContLang
+ // mid-request and see that change reflected in the return value of this function.
+ // Which is insane and would never happen during normal MW operation
+ return $defOpt;
+ }
+
$defOpt = $wgDefaultUserOptions;
# default language setting
$defOpt['variant'] = $wgContLang->getCode();
}
$defOpt['skin'] = $wgDefaultSkin;
- // FIXME: Ideally we'd cache the results of this function so the hook is only run once,
- // but that breaks the parser tests because they rely on being able to change $wgContLang
- // mid-request and see that change reflected in the return value of this function.
- // Which is insane and would never happen during normal MW operation, but is also not
- // likely to get fixed unless and until we context-ify everything.
- // See also https://www.mediawiki.org/wiki/Special:Code/MediaWiki/101488#c25275
wfRunHooks( 'UserGetDefaultOptions', array( &$defOpt ) );
return $defOpt;
global $wgHiddenPrefs;
$this->loadOptions();
- if ( is_null( $this->mOptions ) ) {
- if($defaultOverride != '') {
- return $defaultOverride;
- }
- $this->mOptions = User::getDefaultOptions();
- }
-
# We want 'disabled' preferences to always behave as the default value for
# users, even if they have set the option explicitly in their settings (ie they
# set it, and then it was disabled removing their ability to change it). But
* @param $val mixed New value to set
*/
public function setOption( $oname, $val ) {
- $this->load();
$this->loadOptions();
// Explicitly NULL values should refer to defaults
if( is_null( $val ) ) {
- $defaultOption = self::getDefaultOption( $oname );
- if( !is_null( $defaultOption ) ) {
- $val = $defaultOption;
- }
+ $val = self::getDefaultOption( $oname );
}
$this->mOptions[$oname] = $val;
if( $count === null ) {
// it has not been initialized. do so.
- $dbw = wfGetDB( DB_MASTER );
- $count = $dbr->selectField(
- 'revision', 'count(*)',
- array( 'rev_user' => $this->mId ),
- __METHOD__
- );
- $dbw->update(
- 'user',
- array( 'user_editcount' => $count ),
- array( 'user_id' => $this->mId ),
- __METHOD__
- );
+ $count = $this->initEditCount();
}
wfProfileOut( __METHOD__ );
$this->mEditCount = $count;
}
/**
- * Add this existing user object to the database. If the user already
- * exists, a fatal status object is returned, and the user object is
+ * 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
* }
* // do something with $user...
*
- * However, this was vulnerable to a race condition (bug 16020). By
+ * 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(),
+ * so it is still advisable to make the call conditional on isLoggedIn(),
* and to commit the transaction after calling.
*
* @return Status
array( 'IGNORE' )
);
if ( !$dbw->affectedRows() ) {
- $this->mId = $dbw->selectField( 'user', 'user_id',
+ $this->mId = $dbw->selectField( 'user', 'user_id',
array( 'user_name' => $this->mName ), __METHOD__ );
$loaded = false;
if ( $this->mId ) {
public function incEditCount() {
if( !$this->isAnon() ) {
$dbw = wfGetDB( DB_MASTER );
- $dbw->update( 'user',
+ $dbw->update(
+ 'user',
array( 'user_editcount=user_editcount+1' ),
array( 'user_id' => $this->getId() ),
- __METHOD__ );
+ __METHOD__
+ );
// Lazy initialization check...
if( $dbw->affectedRows() == 0 ) {
- // Pull from a slave to be less cruel to servers
- // Accuracy isn't the point anyway here
- $dbr = wfGetDB( DB_SLAVE );
- $count = $dbr->selectField( 'revision',
- 'COUNT(rev_user)',
- array( 'rev_user' => $this->getId() ),
- __METHOD__ );
-
// Now here's a goddamn hack...
+ $dbr = wfGetDB( DB_SLAVE );
if( $dbr !== $dbw ) {
// If we actually have a slave server, the count is
// at least one behind because the current transaction
// has not been committed and replicated.
- $count++;
+ $this->initEditCount( 1 );
} else {
// But if DB_SLAVE is selecting the master, then the
// count we just read includes the revision that was
// just added in the working transaction.
+ $this->initEditCount();
}
-
- $dbw->update( 'user',
- array( 'user_editcount' => $count ),
- array( 'user_id' => $this->getId() ),
- __METHOD__ );
}
}
// edit count in user cache too
$this->invalidateCache();
}
+ /**
+ * Initialize user_editcount from data out of the revision table
+ *
+ * @param $add Integer Edits to add to the count from the revision table
+ * @return Integer Number of edits
+ */
+ protected function initEditCount( $add = 0 ) {
+ // Pull from a slave to be less cruel to servers
+ // Accuracy isn't the point anyway here
+ $dbr = wfGetDB( DB_SLAVE );
+ $count = $dbr->selectField(
+ 'revision',
+ 'COUNT(rev_user)',
+ array( 'rev_user' => $this->getId() ),
+ __METHOD__
+ );
+ $count = $count + $add;
+
+ $dbw = wfGetDB( DB_MASTER );
+ $dbw->update(
+ 'user',
+ array( 'user_editcount' => $count ),
+ array( 'user_id' => $this->getId() ),
+ __METHOD__
+ );
+
+ return $count;
+ }
+
/**
* Get the description of a given right
*
}
/**
- * @todo document
+ * Load the user options either from cache, the database or an array
+ *
+ * @param $data Rows for the current user out of the user_properties table
*/
- protected function loadOptions() {
+ protected function loadOptions( $data = null ) {
global $wgContLang;
$this->load();
$this->mOptions[$key] = $value;
}
} else {
- wfDebug( "User: loading options for user " . $this->getId() . " from database.\n" );
- // Load from database
- $dbr = wfGetDB( DB_SLAVE );
-
- $res = $dbr->select(
- 'user_properties',
- array( 'up_property', 'up_value' ),
- array( 'up_user' => $this->getId() ),
- __METHOD__
- );
+ if( !is_array( $data ) ) {
+ wfDebug( "User: loading options for user " . $this->getId() . " from database.\n" );
+ // Load from database
+ $dbr = wfGetDB( DB_SLAVE );
- $this->mOptionOverrides = array();
- foreach ( $res as $row ) {
- $this->mOptionOverrides[$row->up_property] = $row->up_value;
- $this->mOptions[$row->up_property] = $row->up_value;
+ $res = $dbr->select(
+ 'user_properties',
+ array( 'up_property', 'up_value' ),
+ array( 'up_user' => $this->getId() ),
+ __METHOD__
+ );
+
+ $this->mOptionOverrides = array();
+ $data = array();
+ foreach ( $res as $row ) {
+ $data[$row->up_property] = $row->up_value;
+ }
+ }
+ foreach ( $data as $property => $value ) {
+ $this->mOptionOverrides[$property] = $value;
+ $this->mOptions[$property] = $value;
}
}