return $u;
}
+ /**
+ * Returns a User object corresponding to the given UserIdentity.
+ *
+ * @since 1.32
+ *
+ * @param UserIdentity $identity
+ *
+ * @return User
+ */
+ public static function newFromIdentity( UserIdentity $identity ) {
+ if ( $identity instanceof User ) {
+ return $identity;
+ }
+
+ return self::newFromAnyId(
+ $identity->getId() === 0 ? null : $identity->getId(),
+ $identity->getName() === '' ? null : $identity->getName(),
+ $identity->getActorId() === 0 ? null : $identity->getActorId()
+ );
+ }
+
/**
* Static factory method for creation from an ID, name, and/or actor ID
*
* will be loaded once more from the database when accessing them.
*
* @param stdClass $row A row from the user table
- * @param array $data Further data to load into the object (see User::loadFromRow for valid keys)
+ * @param array|null $data Further data to load into the object
+ * (see User::loadFromRow for valid keys)
* @return User
*/
public static function newFromRow( $row, $data = null ) {
* @param string|array $groups A single group name or an array of group names
* @param int $limit Max number of users to return. The actual limit will never exceed 5000
* records; larger values are ignored.
- * @param int $after ID the user to start after
+ * @param int|null $after ID the user to start after
* @return UserArrayFromResult
*/
public static function findUsersByGroup( $groups, $limit = 5000, $after = null ) {
$user = $session->getUser();
if ( $user->isLoggedIn() ) {
$this->loadFromUserObject( $user );
-
- // If this user is autoblocked, set a cookie to track the Block. This has to be done on
- // every session load, because an autoblocked editor might not edit again from the same
- // IP address after being blocked.
- $config = RequestContext::getMain()->getConfig();
- if ( $config->get( 'CookieSetOnAutoblock' ) === true ) {
- $block = $this->getBlock();
- $shouldSetCookie = $this->getRequest()->getCookie( 'BlockID' ) === null
- && $block
- && $block->getType() === Block::TYPE_USER
- && $block->isAutoblocking();
- if ( $shouldSetCookie ) {
- wfDebug( __METHOD__ . ': User is autoblocked, setting cookie to track' );
- $block->setCookie( $this->getRequest()->response() );
- }
+ if ( $user->isBlocked() ) {
+ // If this user is autoblocked, set a cookie to track the Block. This has to be done on
+ // every session load, because an autoblocked editor might not edit again from the same
+ // IP address after being blocked.
+ $this->trackBlockWithCookie();
}
// Other code expects these to be set in the session, so set them.
$session->set( 'wsUserID', $this->getId() );
$session->set( 'wsUserName', $this->getName() );
$session->set( 'wsToken', $this->getToken() );
+
return true;
}
+
return false;
}
+ /**
+ * Set the 'BlockID' cookie depending on block type and user authentication status.
+ */
+ public function trackBlockWithCookie() {
+ $block = $this->getBlock();
+ if ( $block && $this->getRequest()->getCookie( 'BlockID' ) === null ) {
+ $config = RequestContext::getMain()->getConfig();
+ $shouldSetCookie = false;
+
+ if ( $this->isAnon() && $config->get( 'CookieSetOnIpBlock' ) ) {
+ // If user is logged-out, set a cookie to track the Block
+ $shouldSetCookie = in_array( $block->getType(), [
+ Block::TYPE_IP, Block::TYPE_RANGE
+ ] );
+ if ( $shouldSetCookie ) {
+ $block->setCookie( $this->getRequest()->response() );
+
+ // temporary measure the use of cookies on ip blocks
+ $stats = MediaWikiServices::getInstance()->getStatsdDataFactory();
+ $stats->increment( 'block.ipblock.setCookie.success' );
+ }
+ } elseif ( $this->isLoggedIn() && $config->get( 'CookieSetOnAutoblock' ) ) {
+ $shouldSetCookie = $block->getType() === Block::TYPE_USER && $block->isAutoblocking();
+ if ( $shouldSetCookie ) {
+ $block->setCookie( $this->getRequest()->response() );
+ }
+ }
+ }
+ }
+
/**
* Load user and user_group data from the database.
* $this->mId must be set, this is how the user is identified.
* Initialize this object from a row from the user table.
*
* @param stdClass $row Row from the user table to load.
- * @param array $data Further user data to load into the object
+ * @param array|null $data Further user data to load into the object
*
* user_groups Array of arrays or stdClass result rows out of the user_groups
* table. Previously you were supposed to pass an array of strings
// An ID was found in the cookie.
$tmpBlock = Block::newFromID( $blockCookieId );
if ( $tmpBlock instanceof Block ) {
- // Check the validity of the block.
- $blockIsValid = $tmpBlock->getType() == Block::TYPE_USER
- && !$tmpBlock->isExpired()
- && $tmpBlock->isAutoblocking();
$config = RequestContext::getMain()->getConfig();
- $useBlockCookie = ( $config->get( 'CookieSetOnAutoblock' ) === true );
+
+ switch ( $tmpBlock->getType() ) {
+ case Block::TYPE_USER:
+ $blockIsValid = !$tmpBlock->isExpired() && $tmpBlock->isAutoblocking();
+ $useBlockCookie = ( $config->get( 'CookieSetOnAutoblock' ) === true );
+ break;
+ case Block::TYPE_IP:
+ case Block::TYPE_RANGE:
+ // If block is type IP or IP range, load only if user is not logged in (T152462)
+ $blockIsValid = !$tmpBlock->isExpired() && !$this->isLoggedIn();
+ $useBlockCookie = ( $config->get( 'CookieSetOnIpBlock' ) === true );
+ break;
+ default:
+ $blockIsValid = false;
+ $useBlockCookie = false;
+ }
+
if ( $blockIsValid && $useBlockCookie ) {
// Use the block.
return $tmpBlock;
/**
* Update the 'You have new messages!' status.
* @param bool $val Whether the user has new messages
- * @param Revision $curRev New, as yet unseen revision of the user talk
+ * @param Revision|null $curRev New, as yet unseen revision of the user talk
* page. Ignored if null or !$val.
*/
public function setNewtalk( $val, $curRev = null ) {
* Get the user's current setting for a given option.
*
* @param string $oname The option to check
- * @param string|array $defaultOverride A default value returned if the option does not exist
+ * @param string|array|null $defaultOverride A default value returned if the option does not exist
* @param bool $ignoreHidden Whether to ignore the effects of $wgHiddenPrefs
* @return string|array|int|null User's current value for the option
* @see getBoolOption()
*
* @see User::listOptionKinds
* @param IContextSource $context
- * @param array $options Assoc. array with options keys to check as keys.
+ * @param array|null $options Assoc. array with options keys to check as keys.
* Defaults to $this->mOptions.
* @return array The key => kind mapping data
*/
if ( ( isset( $info['type'] ) && $info['type'] == 'multiselect' ) ||
( isset( $info['class'] ) && $info['class'] == HTMLMultiSelectField::class ) ) {
$opts = HTMLFormField::flattenOptions( $info['options'] );
- $prefix = isset( $info['prefix'] ) ? $info['prefix'] : $name;
+ $prefix = $info['prefix'] ?? $name;
foreach ( $opts as $value ) {
$multiselectOptions["$prefix$value"] = true;
( isset( $info['class'] ) && $info['class'] == HTMLCheckMatrix::class ) ) {
$columns = HTMLFormField::flattenOptions( $info['columns'] );
$rows = HTMLFormField::flattenOptions( $info['rows'] );
- $prefix = isset( $info['prefix'] ) ? $info['prefix'] : $name;
+ $prefix = $info['prefix'] ?? $name;
foreach ( $columns as $column ) {
foreach ( $rows as $row ) {
* never expire.)
*
* @param string $group Name of the group to add
- * @param string $expiry Optional expiry timestamp in any format acceptable to
+ * @param string|null $expiry Optional expiry timestamp in any format acceptable to
* wfTimestamp(), or null if the group assignment should not expire
* @return bool
*/
*
* @param WebRequest|null $request WebRequest object to use; $wgRequest will be used if null
* is passed.
- * @param bool $secure Whether to force secure/insecure cookies or use default
+ * @param bool|null $secure Whether to force secure/insecure cookies or use default
* @param bool $rememberMe Whether to add a Token cookie for elongated sessions
*/
public function setCookies( $request = null, $secure = null, $rememberMe = false ) {
* @param string $val Input value to compare
* @param string|array $salt Optional function-specific data for hashing
* @param WebRequest|null $request Object to use or null to use $wgRequest
- * @param int $maxage Fail tokens older than this, in seconds
+ * @param int|null $maxage Fail tokens older than this, in seconds
* @return bool Whether the token matches
*/
public function matchEditToken( $val, $salt = '', $request = null, $maxage = null ) {
* @param string $val Input value to compare
* @param string|array $salt Optional function-specific data for hashing
* @param WebRequest|null $request Object to use or null to use $wgRequest
- * @param int $maxage Fail tokens older than this, in seconds
+ * @param int|null $maxage Fail tokens older than this, in seconds
* @return bool Whether the token matches
*/
public function matchEditTokenNoSuffix( $val, $salt = '', $request = null, $maxage = null ) {
* @param string $body Message body
* @param User|null $from Optional sending user; if unspecified, default
* $wgPasswordSender will be used.
- * @param string $replyto Reply-To address
+ * @param string|null $replyto Reply-To address
* @return Status
*/
public function sendMail( $subject, $body, $from = null, $replyto = null ) {
/**
* Load the user options either from cache, the database or an array
*
- * @param array $data Rows for the current user out of the user_properties table
+ * @param array|null $data Rows for the current user out of the user_properties table
*/
protected function loadOptions( $data = null ) {
global $wgContLang;
}
}
+ // Replace deprecated language codes
+ $this->mOptions['language'] = LanguageCode::replaceDeprecatedCodes(
+ $this->mOptions['language']
+ );
+
$this->mOptionsLoaded = true;
Hooks::run( 'UserLoadOptions', [ $this, &$this->mOptions ] );