X-Git-Url: https://git.heureux-cyclage.org/?a=blobdiff_plain;f=includes%2FBlock.php;h=472c36ed19804e4541bf04b848995aefeca57486;hb=a9164f143a59a8d957a1d7f205715ac57fff3c8c;hp=c6b948239c364035e5c5f98f96b22df381bcf403;hpb=61cc4ad178de363342c6d8c60a597e85e9dd1a97;p=lhc%2Fweb%2Fwiklou.git diff --git a/includes/Block.php b/includes/Block.php index c6b948239c..472c36ed19 100644 --- a/includes/Block.php +++ b/includes/Block.php @@ -1,6 +1,6 @@ '', 'user' => null, - 'by' => null, - 'reason' => '', - 'timestamp' => '', 'auto' => false, 'expiry' => '', 'anonOnly' => false, @@ -143,30 +92,16 @@ class Block { 'hideName' => false, 'blockEmail' => false, 'allowUsertalk' => false, - 'byText' => '', - 'systemBlock' => null, 'sitewide' => true, ]; $options += $defaults; - $this->setTarget( $options['address'] ); - if ( $this->target instanceof User && $options['user'] ) { # Needed for foreign users $this->forcedTargetID = $options['user']; } - if ( $options['by'] ) { - # Local user - $this->setBlocker( User::newFromId( $options['by'] ) ); - } else { - # Foreign user - $this->setBlocker( $options['byText'] ); - } - - $this->setReason( $options['reason'] ); - $this->setTimestamp( wfTimestamp( TS_MW, $options['timestamp'] ) ); $this->setExpiry( wfGetDB( DB_REPLICA )->decodeExpiry( $options['expiry'] ) ); # Boolean settings @@ -180,7 +115,6 @@ class Block { $this->isUsertalkEditAllowed( (bool)$options['allowUsertalk'] ); $this->mFromMaster = false; - $this->systemBlockType = $options['systemBlock']; } /** @@ -305,7 +239,9 @@ class Block { && $this->isSitewide() == $block->isSitewide() // Block::getRestrictions() may perform a database query, so keep it at // the end. - && BlockRestriction::equals( $this->getRestrictions(), $block->getRestrictions() ) + && $this->getBlockRestrictionStore()->equals( + $this->getRestrictions(), $block->getRestrictions() + ) ); } @@ -386,12 +322,12 @@ class Block { if ( $block->getType() == self::TYPE_RANGE ) { # This is the number of bits that are allowed to vary in the block, give # or take some floating point errors - $end = Wikimedia\base_convert( $block->getRangeEnd(), 16, 10 ); - $start = Wikimedia\base_convert( $block->getRangeStart(), 16, 10 ); + $prefix = 'v6-'; + $end = Wikimedia\base_convert( ltrim( $block->getRangeEnd(), $prefix ), 16, 10 ); + $start = Wikimedia\base_convert( ltrim( $block->getRangeStart(), $prefix ), 16, 10 ); $size = log( $end - $start + 1, 2 ); - # This has the nice property that a /32 block is ranked equally with a - # single-IP block, which is exactly what it is... + # Rank a range block covering a single IP equally with a single-IP block $score = self::TYPE_RANGE - 1 + ( $size / 128 ); } else { @@ -523,10 +459,10 @@ class Block { $dbw = wfGetDB( DB_MASTER ); - BlockRestriction::deleteByParentBlockId( $this->getId() ); + $this->getBlockRestrictionStore()->deleteByParentBlockId( $this->getId() ); $dbw->delete( 'ipblocks', [ 'ipb_parent_block_id' => $this->getId() ], __METHOD__ ); - BlockRestriction::deleteByBlockId( $this->getId() ); + $this->getBlockRestrictionStore()->deleteByBlockId( $this->getId() ); $dbw->delete( 'ipblocks', [ 'ipb_id' => $this->getId() ], __METHOD__ ); return $dbw->affectedRows() > 0; @@ -543,9 +479,6 @@ class Block { public function insert( $dbw = null ) { global $wgBlockDisablesLogin; - if ( $this->getSystemBlockType() !== null ) { - throw new MWException( 'Cannot insert a system block into the database' ); - } if ( !$this->getBlocker() || $this->getBlocker()->getName() === '' ) { throw new MWException( 'Cannot insert a block without a blocker set' ); } @@ -565,7 +498,7 @@ class Block { if ( $affected ) { $this->setId( $dbw->insertId() ); if ( $this->restrictions ) { - BlockRestriction::insert( $this->restrictions ); + $this->getBlockRestrictionStore()->insert( $this->restrictions ); } } @@ -585,12 +518,12 @@ class Block { ); if ( $ids ) { $dbw->delete( 'ipblocks', [ 'ipb_id' => $ids ], __METHOD__ ); - BlockRestriction::deleteByBlockId( $ids ); + $this->getBlockRestrictionStore()->deleteByBlockId( $ids ); $dbw->insert( 'ipblocks', $row, __METHOD__, [ 'IGNORE' ] ); $affected = $dbw->affectedRows(); $this->setId( $dbw->insertId() ); if ( $this->restrictions ) { - BlockRestriction::insert( $this->restrictions ); + $this->getBlockRestrictionStore()->insert( $this->restrictions ); } } } @@ -634,9 +567,9 @@ class Block { if ( $this->restrictions !== null ) { // An empty array should remove all of the restrictions. if ( empty( $this->restrictions ) ) { - $success = BlockRestriction::deleteByBlockId( $this->getId() ); + $success = $this->getBlockRestrictionStore()->deleteByBlockId( $this->getId() ); } else { - $success = BlockRestriction::update( $this->restrictions ); + $success = $this->getBlockRestrictionStore()->update( $this->restrictions ); } // Update the result. The first false is the result, otherwise, true. $result = $result && $success; @@ -653,11 +586,11 @@ class Block { // Only update the restrictions if they have been modified. if ( $this->restrictions !== null ) { - BlockRestriction::updateByParentBlockId( $this->getId(), $this->restrictions ); + $this->getBlockRestrictionStore()->updateByParentBlockId( $this->getId(), $this->restrictions ); } } else { // autoblock no longer required, delete corresponding autoblock(s) - BlockRestriction::deleteByParentBlockId( $this->getId() ); + $this->getBlockRestrictionStore()->deleteByParentBlockId( $this->getId() ); $dbw->delete( 'ipblocks', [ 'ipb_parent_block_id' => $this->getId() ], @@ -859,11 +792,6 @@ class Block { return false; } - # Don't autoblock for system blocks - if ( $this->getSystemBlockType() !== null ) { - throw new MWException( 'Cannot autoblock from a system block' ); - } - # Check for presence on the autoblock whitelist. if ( self::isWhitelistedFromAutoblocks( $autoblockIP ) ) { return false; @@ -1034,26 +962,7 @@ class Block { } /** - * Get the user id of the blocking sysop - * - * @return int (0 for foreign users) - */ - public function getBy() { - return $this->getBlocker()->getId(); - } - - /** - * Get the username of the blocking sysop - * - * @return string - */ - public function getByName() { - return $this->getBlocker()->getName(); - } - - /** - * Get the block ID - * @return int + * @inheritDoc */ public function getId() { return $this->mId; @@ -1069,61 +978,14 @@ class Block { $this->mId = (int)$blockId; if ( is_array( $this->restrictions ) ) { - $this->restrictions = BlockRestriction::setBlockId( $blockId, $this->restrictions ); + $this->restrictions = $this->getBlockRestrictionStore()->setBlockId( + $blockId, $this->restrictions + ); } return $this; } - /** - * Get the reason given for creating the block - * - * @since 1.33 - * @return string - */ - public function getReason() { - return $this->mReason; - } - - /** - * Set the reason for creating the block - * - * @since 1.33 - * @param string $reason - */ - public function setReason( $reason ) { - $this->mReason = $reason; - } - - /** - * Get whether the block hides the target's username - * - * @since 1.33 - * @return bool The block hides the username - */ - public function getHideName() { - return $this->mHideName; - } - - /** - * Set whether ths block hides the target's username - * - * @since 1.33 - * @param bool $hideName The block hides the username - */ - public function setHideName( $hideName ) { - $this->mHideName = $hideName; - } - - /** - * Get the system block type, if any - * @since 1.29 - * @return string|null - */ - public function getSystemBlockType() { - return $this->systemBlockType; - } - /** * Get/set a flag determining whether the master is used for reads * @@ -1162,165 +1024,6 @@ class Block { : false; } - /** - * Indicates that the block is a sitewide block. This means the user is - * prohibited from editing any page on the site (other than their own talk - * page). - * - * @since 1.33 - * @param null|bool $x - * @return bool - */ - public function isSitewide( $x = null ) { - return wfSetVar( $this->isSitewide, $x ); - } - - /** - * Get or set the flag indicating whether this block blocks the target from - * creating an account. (Note that the flag may be overridden depending on - * global configs.) - * - * @since 1.33 - * @param null|bool $x Value to set (if null, just get the property value) - * @return bool Value of the property - */ - public function isCreateAccountBlocked( $x = null ) { - return wfSetVar( $this->blockCreateAccount, $x ); - } - - /** - * Get or set the flag indicating whether this block blocks the target from - * sending emails. (Note that the flag may be overridden depending on - * global configs.) - * - * @since 1.33 - * @param null|bool $x Value to set (if null, just get the property value) - * @return bool Value of the property - */ - public function isEmailBlocked( $x = null ) { - return wfSetVar( $this->mBlockEmail, $x ); - } - - /** - * Get or set the flag indicating whether this block blocks the target from - * editing their own user talk page. (Note that the flag may be overridden - * depending on global configs.) - * - * @since 1.33 - * @param null|bool $x Value to set (if null, just get the property value) - * @return bool Value of the property - */ - public function isUsertalkEditAllowed( $x = null ) { - return wfSetVar( $this->allowUsertalk, $x ); - } - - /** - * Determine whether the Block prevents a given right. A right - * may be blacklisted or whitelisted, or determined from a - * property on the Block object. For certain rights, the property - * may be overridden according to global configs. - * - * @since 1.33 - * @param string $right Right to check - * @return bool|null null if unrecognized right or unset property - */ - public function appliesToRight( $right ) { - $config = RequestContext::getMain()->getConfig(); - $blockDisablesLogin = $config->get( 'BlockDisablesLogin' ); - - $res = null; - switch ( $right ) { - case 'edit': - // TODO: fix this case to return proper value - $res = true; - break; - case 'createaccount': - $res = $this->isCreateAccountBlocked(); - break; - case 'sendemail': - $res = $this->isEmailBlocked(); - break; - case 'upload': - // Until T6995 is completed - $res = $this->isSitewide(); - break; - case 'read': - $res = false; - break; - case 'purge': - $res = false; - break; - } - if ( !$res && $blockDisablesLogin ) { - // If a block would disable login, then it should - // prevent any right that all users cannot do - $anon = new User; - $res = $anon->isAllowed( $right ) ? $res : true; - } - - return $res; - } - - /** - * Get/set whether the Block prevents a given action - * - * @deprecated since 1.33, use appliesToRight to determine block - * behaviour, and specific methods to get/set properties - * @param string $action Action to check - * @param bool|null $x Value for set, or null to just get value - * @return bool|null Null for unrecognized rights. - */ - public function prevents( $action, $x = null ) { - $config = RequestContext::getMain()->getConfig(); - $blockDisablesLogin = $config->get( 'BlockDisablesLogin' ); - $blockAllowsUTEdit = $config->get( 'BlockAllowsUTEdit' ); - - $res = null; - switch ( $action ) { - case 'edit': - # For now... - $res = true; - break; - case 'createaccount': - $res = wfSetVar( $this->blockCreateAccount, $x ); - break; - case 'sendemail': - $res = wfSetVar( $this->mBlockEmail, $x ); - break; - case 'upload': - // Until T6995 is completed - $res = $this->isSitewide(); - break; - case 'editownusertalk': - // NOTE: this check is not reliable on partial blocks - // since partially blocked users are always allowed to edit - // their own talk page unless a restriction exists on the - // page or User_talk: namespace - wfSetVar( $this->allowUsertalk, $x === null ? null : !$x ); - $res = !$this->isUsertalkEditAllowed(); - - // edit own user talk can be disabled by config - if ( !$blockAllowsUTEdit ) { - $res = true; - } - break; - case 'read': - $res = false; - break; - case 'purge': - $res = false; - break; - } - if ( !$res && $blockDisablesLogin ) { - // If a block would disable login, then it should - // prevent any action that all users cannot do - $anon = new User; - $res = $anon->isAllowed( $action ) ? $res : true; - } - - return $res; - } - /** * Get the block name, but with autoblocked IPs hidden as per standard privacy policy * @return string Text is escaped @@ -1367,7 +1070,9 @@ class Block { $fname ); if ( $ids ) { - BlockRestriction::deleteByBlockId( $ids ); + $blockRestrictionStore = MediaWikiServices::getInstance()->getBlockRestrictionStore(); + $blockRestrictionStore->deleteByBlockId( $ids ); + $dbw->delete( 'ipblocks', [ 'ipb_id' => $ids ], $fname ); } } @@ -1608,170 +1313,15 @@ class Block { } /** - * From an existing Block, get the target and the type of target. - * Note that, except for null, it is always safe to treat the target - * as a string; for User objects this will return User::__toString() - * which in turn gives User::getName(). + * @inheritDoc * - * @param string|int|User|null $target - * @return array [ User|String|null, Block::TYPE_ constant|null ] - */ - public static function parseTarget( $target ) { - # We may have been through this before - if ( $target instanceof User ) { - if ( IP::isValid( $target->getName() ) ) { - return [ $target, self::TYPE_IP ]; - } else { - return [ $target, self::TYPE_USER ]; - } - } elseif ( $target === null ) { - return [ null, null ]; - } - - $target = trim( $target ); - - if ( IP::isValid( $target ) ) { - # We can still create a User if it's an IP address, but we need to turn - # off validation checking (which would exclude IP addresses) - return [ - User::newFromName( IP::sanitizeIP( $target ), false ), - self::TYPE_IP - ]; - - } elseif ( IP::isValidRange( $target ) ) { - # Can't create a User from an IP range - return [ IP::sanitizeRange( $target ), self::TYPE_RANGE ]; - } - - # Consider the possibility that this is not a username at all - # but actually an old subpage (T31797) - if ( strpos( $target, '/' ) !== false ) { - # An old subpage, drill down to the user behind it - $target = explode( '/', $target )[0]; - } - - $userObj = User::newFromName( $target ); - if ( $userObj instanceof User ) { - # Note that since numbers are valid usernames, a $target of "12345" will be - # considered a User. If you want to pass a block ID, prepend a hash "#12345", - # since hash characters are not valid in usernames or titles generally. - return [ $userObj, self::TYPE_USER ]; - - } elseif ( preg_match( '/^#\d+$/', $target ) ) { - # Autoblock reference in the form "#12345" - return [ substr( $target, 1 ), self::TYPE_AUTO ]; - - } else { - # WTF? - return [ null, null ]; - } - } - - /** - * Get the type of target for this particular block. Autoblocks have whichever type - * corresponds to their target, so to detect if a block is an autoblock, we have to - * check the mAuto property instead. - * @return int Block::TYPE_ constant, will never be TYPE_ID + * Autoblocks have whichever type corresponds to their target, so to detect if a block is an + * autoblock, we have to check the mAuto property instead. */ public function getType() { return $this->mAuto ? self::TYPE_AUTO - : $this->type; - } - - /** - * Get the target and target type for this particular Block. Note that for autoblocks, - * this returns the unredacted name; frontend functions need to call $block->getRedactedName() - * in this situation. - * @return array [ User|String, Block::TYPE_ constant ] - * @todo FIXME: This should be an integral part of the Block member variables - */ - public function getTargetAndType() { - return [ $this->getTarget(), $this->getType() ]; - } - - /** - * 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 - */ - public function getTarget() { - return $this->target; - } - - /** - * Get the block expiry time - * - * @since 1.19 - * @return string - */ - public function getExpiry() { - return $this->mExpiry; - } - - /** - * Set the block expiry time - * - * @since 1.33 - * @param string $expiry - */ - public function setExpiry( $expiry ) { - $this->mExpiry = $expiry; - } - - /** - * Get the timestamp indicating when the block was created - * - * @since 1.33 - * @return string - */ - public function getTimestamp() { - return $this->mTimestamp; - } - - /** - * Set the timestamp indicating when the block was created - * - * @since 1.33 - * @param string $timestamp - */ - public function setTimestamp( $timestamp ) { - $this->mTimestamp = $timestamp; - } - - /** - * Set the target for this block, and update $this->type accordingly - * @param mixed $target - */ - public function setTarget( $target ) { - list( $this->target, $this->type ) = self::parseTarget( $target ); - } - - /** - * Get the user who implemented this block - * @return User User object. May name a foreign user. - */ - public function getBlocker() { - return $this->blocker; - } - - /** - * Set the user who implemented (or will implement) this block - * @param User|string $user Local User object or username string - */ - public function setBlocker( $user ) { - if ( is_string( $user ) ) { - $user = User::newFromName( $user, false ); - } - - if ( $user->isAnon() && User::isUsableName( $user->getName() ) ) { - throw new InvalidArgumentException( - 'Blocker must be a local user or a name that cannot be a local user' - ); - } - - $this->blocker = $user; + : parent::getType(); } /** @@ -1863,19 +1413,15 @@ class Block { } /** - * Get the key and parameters for the corresponding error message. + * @inheritDoc * - * @since 1.22 - * @param IContextSource $context - * @return array + * Build different messages for autoblocks and partial blocks. */ public function getPermissionsError( IContextSource $context ) { $params = $this->getBlockErrorParams( $context ); $msg = 'blockedtext'; - if ( $this->getSystemBlockType() !== null ) { - $msg = 'systemblockedtext'; - } elseif ( $this->mAuto ) { + if ( $this->mAuto ) { $msg = 'autoblockedtext'; } elseif ( !$this->isSitewide() ) { $msg = 'blockedtext-partial'; @@ -1886,45 +1432,6 @@ class Block { return $params; } - /** - * Get block information used in different block error messages - * - * @since 1.33 - * @param IContextSource $context - * @return array - */ - public function getBlockErrorParams( IContextSource $context ) { - $blocker = $this->getBlocker(); - if ( $blocker instanceof User ) { // local user - $blockerUserpage = $blocker->getUserPage(); - $link = "[[{$blockerUserpage->getPrefixedText()}|{$blockerUserpage->getText()}]]"; - } else { // foreign user - $link = $blocker; - } - - $reason = $this->getReason(); - if ( $reason == '' ) { - $reason = $context->msg( 'blockednoreason' )->text(); - } - - /* $ip returns who *is* being blocked, $intended contains who was meant to be blocked. - * This could be a username, an IP range, or a single IP. */ - $intended = $this->getTarget(); - $systemBlockType = $this->getSystemBlockType(); - $lang = $context->getLanguage(); - - return [ - $link, - $reason, - $context->getRequest()->getIP(), - $this->getByName(), - $systemBlockType ?? $this->getId(), - $lang->formatExpiry( $this->getExpiry() ), - (string)$intended, - $lang->userTimeAndDate( $this->getTimestamp(), $context->getUser() ), - ]; - } - /** * Get Restrictions. * @@ -1941,7 +1448,7 @@ class Block { if ( !$this->mId ) { return []; } - $this->restrictions = BlockRestriction::loadByBlockId( $this->mId ); + $this->restrictions = $this->getBlockRestrictionStore()->loadByBlockId( $this->mId ); } return $this->restrictions; @@ -1963,76 +1470,7 @@ class Block { } /** - * Determine whether the block allows the user to edit their own - * user talk page. This is done separately from Block::appliesToRight - * because there is no right for editing one's own user talk page - * and because the user's talk page needs to be passed into the - * Block object, which is unaware of the user. - * - * The ipb_allow_usertalk flag (which corresponds to the property - * allowUsertalk) is used on sitewide blocks and partial blocks - * that contain a namespace restriction on the user talk namespace, - * but do not contain a page restriction on the user's talk page. - * For all other (i.e. most) partial blocks, the flag is ignored, - * and the user can always edit their user talk page unless there - * is a page restriction on their user talk page, in which case - * they can never edit it. (Ideally the flag would be stored as - * null in these cases, but the database field isn't nullable.) - * - * This method does not validate that the passed in talk page belongs to the - * block target since the target (an IP) might not be the same as the user's - * talk page (if they are logged in). - * - * @since 1.33 - * @param Title|null $usertalk The user's user talk page. If null, - * and if the target is a User, the target's userpage is used - * @return bool The user can edit their talk page - */ - public function appliesToUsertalk( Title $usertalk = null ) { - if ( !$usertalk ) { - if ( $this->target instanceof User ) { - $usertalk = $this->target->getTalkPage(); - } else { - throw new InvalidArgumentException( - '$usertalk must be provided if block target is not a user/IP' - ); - } - } - - if ( $usertalk->getNamespace() !== NS_USER_TALK ) { - throw new InvalidArgumentException( - '$usertalk must be a user talk page' - ); - } - - if ( !$this->isSitewide() ) { - if ( $this->appliesToPage( $usertalk->getArticleID() ) ) { - return true; - } - if ( !$this->appliesToNamespace( NS_USER_TALK ) ) { - return false; - } - } - - // This is a type of block which uses the ipb_allow_usertalk - // flag. The flag can still be overridden by global configs. - $config = RequestContext::getMain()->getConfig(); - if ( !$config->get( 'BlockAllowsUTEdit' ) ) { - return true; - } - return !$this->isUsertalkEditAllowed(); - } - - /** - * Checks if a block applies to a particular title - * - * This check does not consider whether `$this->isUsertalkEditAllowed` - * returns false, as the identity of the user making the hypothetical edit - * isn't known here (particularly in the case of IP hardblocks, range - * blocks, and auto-blocks). - * - * @param Title $title - * @return bool + * @inheritDoc */ public function appliesToTitle( Title $title ) { if ( $this->isSitewide() ) { @@ -2050,12 +1488,7 @@ class Block { } /** - * Checks if a block applies to a particular namespace - * - * @since 1.33 - * - * @param int $ns - * @return bool + * @inheritDoc */ public function appliesToNamespace( $ns ) { if ( $this->isSitewide() ) { @@ -2073,17 +1506,7 @@ class Block { } /** - * Checks if a block applies to a particular page - * - * This check does not consider whether `$this->isUsertalkEditAllowed` - * returns false, as the identity of the user making the hypothetical edit - * isn't known here (particularly in the case of IP hardblocks, range - * blocks, and auto-blocks). - * - * @since 1.33 - * - * @param int $pageId - * @return bool + * @inheritDoc */ public function appliesToPage( $pageId ) { if ( $this->isSitewide() ) { @@ -2123,44 +1546,27 @@ class Block { } /** - * Check if the block should be tracked with a cookie. - * - * @since 1.33 - * @param bool $isIpUser The user is logged out - * @return bool The block should be tracked with a cookie + * @inheritDoc */ - public function shouldTrackWithCookie( $isIpUser ) { + public function shouldTrackWithCookie( $isAnon ) { $config = RequestContext::getMain()->getConfig(); switch ( $this->getType() ) { case self::TYPE_IP: case self::TYPE_RANGE: - return $isIpUser && $config->get( 'CookieSetOnIpBlock' ); + return $isAnon && $config->get( 'CookieSetOnIpBlock' ); case self::TYPE_USER: - return !$isIpUser && $config->get( 'CookieSetOnAutoblock' ) && $this->isAutoblocking(); + return !$isAnon && $config->get( 'CookieSetOnAutoblock' ) && $this->isAutoblocking(); default: return false; } } /** - * Check if the block prevents a user from resetting their password + * Get a BlockRestrictionStore instance * - * @since 1.33 - * @return bool The block blocks password reset + * @return BlockRestrictionStore */ - public function appliesToPasswordReset() { - switch ( $this->getSystemBlockType() ) { - case null: - case 'global-block': - return $this->isCreateAccountBlocked(); - case 'proxy': - return true; - case 'dnsbl': - case 'wgSoftBlockRanges': - return false; - default: - return true; - } + private function getBlockRestrictionStore() : BlockRestrictionStore { + return MediaWikiServices::getInstance()->getBlockRestrictionStore(); } - }