diff options
Diffstat (limited to 'includes/Block.php')
-rw-r--r-- | includes/Block.php | 370 |
1 files changed, 161 insertions, 209 deletions
diff --git a/includes/Block.php b/includes/Block.php index 34b89e73..6a29a056 100644 --- a/includes/Block.php +++ b/includes/Block.php @@ -20,33 +20,54 @@ * @file */ class Block { - /* public*/ var $mReason, $mTimestamp, $mAuto, $mExpiry, $mHideName; + /** @var string */ + public $mReason; - protected - $mId, - $mFromMaster, + /** @var bool|string */ + public $mTimestamp; - $mBlockEmail, - $mDisableUsertalk, - $mCreateAccount, - $mParentBlockId; + /** @var int */ + public $mAuto; - /// @var User|String + /** @var bool|string */ + public $mExpiry; + + public $mHideName; + + /** @var int */ + public $mParentBlockId; + + /** @var int */ + protected $mId; + + /** @var bool */ + protected $mFromMaster; + + /** @var bool */ + protected $mBlockEmail; + + /** @var bool */ + protected $mDisableUsertalk; + + /** @var bool */ + protected $mCreateAccount; + + /** @var User|string */ protected $target; - // @var Integer Hack for foreign blocking (CentralAuth) + /** @var int Hack for foreign blocking (CentralAuth) */ protected $forcedTargetID; - /// @var Block::TYPE_ constant. Can only be USER, IP or RANGE internally + /** @var int Block::TYPE_ constant. Can only be USER, IP or RANGE internally */ protected $type; - /// @var User + /** @var User */ protected $blocker; - /// @var Bool + /** @var bool */ protected $isHardblock = true; - /// @var Bool + /** @var bool */ protected $isAutoblocking = true; # TYPE constants @@ -57,14 +78,27 @@ class Block { const TYPE_ID = 5; /** - * Constructor - * @todo FIXME: Don't know what the best format to have for this constructor is, but fourteen - * optional parameters certainly isn't it. + * @todo FIXME: Don't know what the best format to have for this constructor + * is, but fourteen optional parameters certainly isn't it. + * @param string $address + * @param int $user + * @param int $by + * @param string $reason + * @param mixed $timestamp + * @param int $auto + * @param string $expiry + * @param int $anonOnly + * @param int $createAccount + * @param int $enableAutoblock + * @param int $hideName + * @param int $blockEmail + * @param int $allowUsertalk + * @param string $byText */ function __construct( $address = '', $user = 0, $by = 0, $reason = '', $timestamp = 0, $auto = 0, $expiry = '', $anonOnly = 0, $createAccount = 0, $enableAutoblock = 0, - $hideName = 0, $blockEmail = 0, $allowUsertalk = 0, $byText = '' ) - { + $hideName = 0, $blockEmail = 0, $allowUsertalk = 0, $byText = '' + ) { if ( $timestamp === 0 ) { $timestamp = wfTimestampNow(); } @@ -102,25 +136,10 @@ class Block { } /** - * Load a block from the database, using either the IP address or - * user ID. Tries the user ID first, and if that doesn't work, tries - * the address. - * - * @param string $address IP address of user/anon - * @param $user Integer: user id of user - * @return Block Object - * @deprecated since 1.18 - */ - public static function newFromDB( $address, $user = 0 ) { - wfDeprecated( __METHOD__, '1.18' ); - return self::newFromTarget( User::whoIs( $user ), $address ); - } - - /** * Load a blocked user from their block id. * - * @param $id Integer: Block id to search for - * @return Block object or null + * @param int $id Block id to search for + * @return Block|null */ public static function newFromID( $id ) { $dbr = wfGetDB( DB_SLAVE ); @@ -166,7 +185,7 @@ class Block { * Check if two blocks are effectively equal. Doesn't check irrelevant things like * the blocking user or the block timestamp, only things which affect the blocked user * - * @param $block Block + * @param Block $block * * @return bool */ @@ -187,52 +206,14 @@ class Block { } /** - * Clear all member variables in the current object. Does not clear - * the block from the DB. - * @deprecated since 1.18 - */ - public function clear() { - wfDeprecated( __METHOD__, '1.18' ); - # Noop - } - - /** - * Get a block from the DB, with either the given address or the given username - * - * @param string $address The IP address of the user, or blank to skip IP blocks - * @param int $user The user ID, or zero for anonymous users - * @return Boolean: the user is blocked from editing - * @deprecated since 1.18 - */ - public function load( $address = '', $user = 0 ) { - wfDeprecated( __METHOD__, '1.18' ); - if ( $user ) { - $username = User::whoIs( $user ); - $block = self::newFromTarget( $username, $address ); - } else { - $block = self::newFromTarget( null, $address ); - } - - if ( $block instanceof Block ) { - # This is mildly evil, but hey, it's B/C :D - foreach ( $block as $variable => $value ) { - $this->$variable = $value; - } - return true; - } else { - return false; - } - } - - /** * Load a block from the database which affects the already-set $this->target: * 1) A block directly on the given user or IP * 2) A rangeblock encompassing the given IP (smallest first) * 3) An autoblock on the given IP - * @param $vagueTarget User|String also search for blocks affecting this target. Doesn't + * @param User|string $vagueTarget Also search for blocks affecting this target. Doesn't * make any sense to use TYPE_AUTO / TYPE_ID here. Leave blank to skip IP lookups. * @throws MWException - * @return Bool whether a relevant block was found + * @return bool Whether a relevant block was found */ protected function newLoad( $vagueTarget = null ) { $db = wfGetDB( $this->mFromMaster ? DB_MASTER : DB_SLAVE ); @@ -333,7 +314,7 @@ class Block { * Get a set of SQL conditions which will select rangeblocks encompassing a given range * @param string $start Hexadecimal IP representation * @param string $end Hexadecimal IP representation, or null to use $start = $end - * @return String + * @return string */ public static function getRangeCond( $start, $end = null ) { if ( $end === null ) { @@ -365,8 +346,8 @@ class Block { /** * Get the component of an IP address which is certain to be the same between an IP * address and a rangeblock containing that IP address. - * @param $hex String Hexadecimal IP representation - * @return String + * @param string $hex Hexadecimal IP representation + * @return string */ protected static function getIpFragment( $hex ) { global $wgBlockCIDRLimit; @@ -380,7 +361,7 @@ class Block { /** * Given a database row from the ipblocks table, initialize * member variables - * @param $row ResultWrapper: a row from the ipblocks table + * @param stdClass $row A row from the ipblocks table */ protected function initFromRow( $row ) { $this->setTarget( $row->ipb_address ); @@ -415,7 +396,7 @@ class Block { /** * Create a new Block object from a database row - * @param $row ResultWrapper row from the ipblocks table + * @param stdClass $row Row from the ipblocks table * @return Block */ public static function newFromRow( $row ) { @@ -428,7 +409,7 @@ class Block { * Delete the row from the IP blocks table. * * @throws MWException - * @return Boolean + * @return bool */ public function delete() { if ( wfReadOnly() ) { @@ -450,8 +431,8 @@ class Block { * Insert a block into the block table. Will fail if there is a conflicting * block (same name and options) already in the database. * - * @param $dbw DatabaseBase if you have one available - * @return mixed: false on failure, assoc array on success: + * @param DatabaseBase $dbw If you have one available + * @return bool|array False on failure, assoc array on success: * ('id' => block ID, 'autoIds' => array of autoblock IDs) */ public function insert( $dbw = null ) { @@ -488,13 +469,15 @@ class Block { * Update a block in the DB with new parameters. * The ID field needs to be loaded first. * - * @return Int number of affected rows, which should probably be 1 or something has - * gone slightly awry + * @return bool|array False on failure, array on success: + * ('id' => block ID, 'autoIds' => array of autoblock IDs) */ public function update() { wfDebug( "Block::update; timestamp {$this->mTimestamp}\n" ); $dbw = wfGetDB( DB_MASTER ); + $dbw->startAtomic( __METHOD__ ); + $dbw->update( 'ipblocks', $this->getDatabaseArray( $dbw ), @@ -502,13 +485,39 @@ class Block { __METHOD__ ); - return $dbw->affectedRows(); + $affected = $dbw->affectedRows(); + + if ( $this->isAutoblocking() ) { + // update corresponding autoblock(s) (bug 48813) + $dbw->update( + 'ipblocks', + $this->getAutoblockUpdateArray(), + array( 'ipb_parent_block_id' => $this->getId() ), + __METHOD__ + ); + } else { + // autoblock no longer required, delete corresponding autoblock(s) + $dbw->delete( + 'ipblocks', + array( 'ipb_parent_block_id' => $this->getId() ), + __METHOD__ + ); + } + + $dbw->endAtomic( __METHOD__ ); + + if ( $affected ) { + $auto_ipd_ids = $this->doRetroactiveAutoblock(); + return array( 'id' => $this->mId, 'autoIds' => $auto_ipd_ids ); + } + + return false; } /** * Get an array suitable for passing to $dbw->insert() or $dbw->update() - * @param $db DatabaseBase - * @return Array + * @param DatabaseBase $db + * @return array */ protected function getDatabaseArray( $db = null ) { if ( !$db ) { @@ -546,10 +555,24 @@ class Block { } /** + * @return array + */ + protected function getAutoblockUpdateArray() { + return array( + 'ipb_by' => $this->getBy(), + 'ipb_by_text' => $this->getByName(), + 'ipb_reason' => $this->mReason, + 'ipb_create_account' => $this->prevents( 'createaccount' ), + 'ipb_deleted' => (int)$this->mHideName, // typecast required for SQLite + 'ipb_allow_usertalk' => !$this->prevents( 'editownusertalk' ), + ); + } + + /** * Retroactively autoblocks the last IP used by the user (if it is a user) * blocked by this Block. * - * @return Array: block IDs of retroactive autoblocks made + * @return array Block IDs of retroactive autoblocks made */ protected function doRetroactiveAutoblock() { $blockIds = array(); @@ -573,7 +596,6 @@ class Block { * * @param Block $block * @param array &$blockIds - * @return Array: block IDs of retroactive autoblocks made */ protected static function defaultRetroactiveAutoblock( Block $block, array &$blockIds ) { global $wgPutIPinRC; @@ -614,7 +636,7 @@ class Block { * TODO: this probably belongs somewhere else, but not sure where... * * @param string $ip The IP to check - * @return Boolean + * @return bool */ public static function isWhitelistedFromAutoblocks( $ip ) { global $wgMemc; @@ -656,8 +678,8 @@ class Block { /** * Autoblocks the given IP, referring to this Block. * - * @param string $autoblockIP the IP to autoblock. - * @return mixed: block ID if an autoblock was inserted, false if not. + * @param string $autoblockIP The IP to autoblock. + * @return int|bool Block ID if an autoblock was inserted, false if not. */ public function doAutoblock( $autoblockIP ) { # If autoblocks are disabled, go away. @@ -698,7 +720,8 @@ class Block { wfDebug( "Autoblocking {$this->getTarget()}@" . $autoblockIP . "\n" ); $autoblock->setTarget( $autoblockIP ); $autoblock->setBlocker( $this->getBlocker() ); - $autoblock->mReason = wfMessage( 'autoblocker', $this->getTarget(), $this->mReason )->inContentLanguage()->plain(); + $autoblock->mReason = wfMessage( 'autoblocker', $this->getTarget(), $this->mReason ) + ->inContentLanguage()->plain(); $timestamp = wfTimestampNow(); $autoblock->mTimestamp = $timestamp; $autoblock->mAuto = 1; @@ -726,7 +749,7 @@ class Block { /** * Check if a block has expired. Delete it if it is. - * @return Boolean + * @return bool */ public function deleteIfExpired() { wfProfileIn( __METHOD__ ); @@ -746,7 +769,7 @@ class Block { /** * Has the block expired? - * @return Boolean + * @return bool */ public function isExpired() { $timestamp = wfTimestampNow(); @@ -761,7 +784,7 @@ class Block { /** * Is the block address valid (i.e. not a null string?) - * @return Boolean + * @return bool */ public function isValid() { return $this->getTarget() != null; @@ -792,7 +815,7 @@ class Block { /** * Get the IP address at the start of the range in Hex form * @throws MWException - * @return String IP in Hex form + * @return string IP in Hex form */ public function getRangeStart() { switch ( $this->type ) { @@ -811,7 +834,7 @@ class Block { /** * Get the IP address at the end of the range in Hex form * @throws MWException - * @return String IP in Hex form + * @return string IP in Hex form */ public function getRangeEnd() { switch ( $this->type ) { @@ -830,7 +853,7 @@ class Block { /** * Get the user id of the blocking sysop * - * @return Integer (0 for foreign users) + * @return int (0 for foreign users) */ public function getBy() { $blocker = $this->getBlocker(); @@ -842,7 +865,7 @@ class Block { /** * Get the username of the blocking sysop * - * @return String + * @return string */ public function getByName() { $blocker = $this->getBlocker(); @@ -860,21 +883,10 @@ class Block { } /** - * Get/set the SELECT ... FOR UPDATE flag - * @deprecated since 1.18 - * - * @param $x Bool - */ - public function forUpdate( $x = null ) { - wfDeprecated( __METHOD__, '1.18' ); - # noop - } - - /** * Get/set a flag determining whether the master is used for reads * - * @param $x Bool - * @return Bool + * @param bool $x + * @return bool */ public function fromMaster( $x = null ) { return wfSetVar( $this->mFromMaster, $x ); @@ -882,8 +894,8 @@ class Block { /** * Get/set whether the Block is a hardblock (affects logged-in users on a given IP/range - * @param $x Bool - * @return Bool + * @param bool $x + * @return bool */ public function isHardblock( $x = null ) { wfSetVar( $this->isHardblock, $x ); @@ -906,9 +918,9 @@ class Block { /** * Get/set whether the Block prevents a given action - * @param $action String - * @param $x Bool - * @return Bool + * @param string $action + * @param bool $x + * @return bool */ public function prevents( $action, $x = null ) { switch ( $action ) { @@ -932,7 +944,7 @@ class Block { /** * Get the block name, but with autoblocked IPs hidden as per standard privacy policy - * @return String, text is escaped + * @return string Text is escaped */ public function getRedactedName() { if ( $this->mAuto ) { @@ -947,37 +959,10 @@ class Block { } /** - * Encode expiry for DB - * - * @param string $expiry timestamp for expiry, or - * @param $db DatabaseBase object - * @return String - * @deprecated since 1.18; use $dbw->encodeExpiry() instead - */ - public static function encodeExpiry( $expiry, $db ) { - wfDeprecated( __METHOD__, '1.18' ); - return $db->encodeExpiry( $expiry ); - } - - /** - * Decode expiry which has come from the DB - * - * @param string $expiry Database expiry format - * @param int $timestampType Requested timestamp format - * @return String - * @deprecated since 1.18; use $wgLang->formatExpiry() instead - */ - public static function decodeExpiry( $expiry, $timestampType = TS_MW ) { - wfDeprecated( __METHOD__, '1.18' ); - global $wgContLang; - return $wgContLang->formatExpiry( $expiry, $timestampType ); - } - - /** * Get a timestamp of the expiry for autoblocks * - * @param $timestamp String|Int - * @return String + * @param string|int $timestamp + * @return string */ public static function getAutoblockExpiry( $timestamp ) { global $wgAutoblockExpiry; @@ -986,18 +971,6 @@ class Block { } /** - * Gets rid of unneeded numbers in quad-dotted/octet IP strings - * For example, 127.111.113.151/24 -> 127.111.113.0/24 - * @param string $range IP address to normalize - * @return string - * @deprecated since 1.18, call IP::sanitizeRange() directly - */ - public static function normaliseRange( $range ) { - wfDeprecated( __METHOD__, '1.18' ); - return IP::sanitizeRange( $range ); - } - - /** * Purge expired blocks from the ipblocks table */ public static function purgeExpired() { @@ -1007,38 +980,15 @@ class Block { $method = __METHOD__; $dbw = wfGetDB( DB_MASTER ); - $dbw->onTransactionIdle( function() use ( $dbw, $method ) { + $dbw->onTransactionIdle( function () use ( $dbw, $method ) { $dbw->delete( 'ipblocks', array( 'ipb_expiry < ' . $dbw->addQuotes( $dbw->timestamp() ) ), $method ); } ); } /** - * Get a value to insert into expiry field of the database when infinite expiry - * is desired - * @deprecated since 1.18, call $dbr->getInfinity() directly - * @return String - */ - public static function infinity() { - wfDeprecated( __METHOD__, '1.18' ); - return wfGetDB( DB_SLAVE )->getInfinity(); - } - - /** - * Convert a submitted expiry time, which may be relative ("2 weeks", etc) or absolute - * ("24 May 2034"), into an absolute timestamp we can put into the database. - * @param string $expiry whatever was typed into the form - * @return String: timestamp or "infinity" string for th DB implementation - * @deprecated since 1.18 moved to SpecialBlock::parseExpiryInput() - */ - public static function parseExpiryInput( $expiry ) { - wfDeprecated( __METHOD__, '1.18' ); - return SpecialBlock::parseExpiryInput( $expiry ); - } - - /** * Given a target and the target's type, get an existing Block object if possible. - * @param $specificTarget String|User|Int a block target, which may be one of several types: + * @param string|User|int $specificTarget A block target, which may be one of several types: * * A user to block, in which case $target will be a User * * An IP to block, in which case $target will be a User generated by using * User::newFromName( $ip, false ) to turn off name validation @@ -1048,10 +998,10 @@ class Block { * Calling this with a user, IP address or range will not select autoblocks, and will * only select a block where the targets match exactly (so looking for blocks on * 1.2.3.4 will not select 1.2.0.0/16 or even 1.2.3.4/32) - * @param $vagueTarget String|User|Int as above, but we will search for *any* block which + * @param string|User|int $vagueTarget As above, but we will search for *any* block which * affects that target (so for an IP address, get ranges containing that IP; and also * get any relevant autoblocks). Leave empty or blank to skip IP-based lookups. - * @param bool $fromMaster whether to use the DB_MASTER database + * @param bool $fromMaster Whether to use the DB_MASTER database * @return Block|null (null if no relevant block could be found). The target and type * of the returned Block will refer to the actual block which was found, which might * not be the same as the target you gave if you used $vagueTarget! @@ -1068,7 +1018,10 @@ class Block { # passed by some callers (bug 29116) return null; - } elseif ( in_array( $type, array( Block::TYPE_USER, Block::TYPE_IP, Block::TYPE_RANGE, null ) ) ) { + } elseif ( in_array( + $type, + array( Block::TYPE_USER, Block::TYPE_IP, Block::TYPE_RANGE, null ) ) + ) { $block = new Block(); $block->fromMaster( $fromMaster ); @@ -1083,15 +1036,14 @@ class Block { return null; } - /** * Get all blocks that match any IP from an array of IP addresses * - * @param Array $ipChain list of IPs (strings), usually retrieved from the + * @param array $ipChain List of IPs (strings), usually retrieved from the * X-Forwarded-For header of the request - * @param Bool $isAnon Exclude anonymous-only blocks if false - * @param Bool $fromMaster Whether to query the master or slave database - * @return Array of Blocks + * @param bool $isAnon Exclude anonymous-only blocks if false + * @param bool $fromMaster Whether to query the master or slave database + * @return array Array of Blocks * @since 1.22 */ public static function getBlocksForIPList( array $ipChain, $isAnon, $fromMaster = false ) { @@ -1111,7 +1063,7 @@ class Block { continue; } # Don't check trusted IPs (includes local squids which will be in every request) - if ( wfIsTrustedProxy( $ipaddr ) ) { + if ( IP::isTrustedProxy( $ipaddr ) ) { continue; } # Check both the original IP (to check against single blocks), as well as build @@ -1165,13 +1117,13 @@ class Block { * - Other softblocks are chosen over autoblocks * - If there are multiple exact or range blocks at the same level, the one chosen * is random - - * @param Array $ipChain list of IPs (strings). This is used to determine how "close" + * + * @param array $blocks Array of blocks + * @param array $ipChain List of IPs (strings). This is used to determine how "close" * a block is to the server, and if a block matches exactly, or is in a range. * The order is furthest from the server to nearest e.g., (Browser, proxy1, proxy2, * local-squid, ...) - * @param Array $block Array of blocks - * @return Block|null the "best" block from the list + * @return Block|null The "best" block from the list */ public static function chooseBlock( array $blocks, array $ipChain ) { if ( !count( $blocks ) ) { @@ -1184,7 +1136,7 @@ class Block { // Sort hard blocks before soft ones and secondarily sort blocks // that disable account creation before those that don't. - usort( $blocks, function( Block $a, Block $b ) { + usort( $blocks, function ( Block $a, Block $b ) { $aWeight = (int)$a->isHardblock() . (int)$a->prevents( 'createaccount' ); $bWeight = (int)$b->isHardblock() . (int)$b->prevents( 'createaccount' ); return strcmp( $bWeight, $aWeight ); // highest weight first @@ -1275,7 +1227,7 @@ class Block { * as a string; for User objects this will return User::__toString() * which in turn gives User::getName(). * - * @param $target String|Int|User|null + * @param string|int|User|null $target * @return array( User|String|null, Block::TYPE_ constant|null ) */ public static function parseTarget( $target ) { @@ -1332,7 +1284,7 @@ class Block { /** * Get the type of target for this particular block - * @return Block::TYPE_ constant, will never be TYPE_ID + * @return int Block::TYPE_ constant, will never be TYPE_ID */ public function getType() { return $this->mAuto @@ -1355,7 +1307,7 @@ class Block { * Get the target for this particular Block. Note that for autoblocks, * this returns the unredacted name; frontend functions need to call $block->getRedactedName() * in this situation. - * @return User|String + * @return User|string */ public function getTarget() { return $this->target; @@ -1364,7 +1316,7 @@ class Block { /** * @since 1.19 * - * @return Mixed|string + * @return mixed|string */ public function getExpiry() { return $this->mExpiry; @@ -1372,7 +1324,7 @@ class Block { /** * Set the target for this block, and update $this->type accordingly - * @param $target Mixed + * @param mixed $target */ public function setTarget( $target ) { list( $this->target, $this->type ) = self::parseTarget( $target ); @@ -1388,7 +1340,7 @@ class Block { /** * Set the user who implemented (or will implement) this block - * @param $user User|string Local User object or username string for foreign users + * @param User|string $user Local User object or username string for foreign users */ public function setBlocker( $user ) { $this->blocker = $user; @@ -1429,7 +1381,7 @@ class Block { $this->getId(), $lang->formatExpiry( $this->mExpiry ), (string)$intended, - $lang->timeanddate( wfTimestamp( TS_MW, $this->mTimestamp ), true ), + $lang->userTimeAndDate( $this->mTimestamp, $context->getUser() ), ); } } |