From f34423130fee55974a5aec783cd34a213802bd1c Mon Sep 17 00:00:00 2001 From: Brad Jorsch Date: Thu, 22 Mar 2018 12:52:59 -0400 Subject: [PATCH] User: Fully clear instance variables when loading not-blocked status If a block is deleted and ->clearInstanceCache() is called to try to make an existing User object reflect that fact, some methods are still reflecting the old block. To fix this, User::getBlockedStatus() needs to clear all the relevant instance variables if the user is found not to be blocked. Change-Id: I6ad8d5555a4c8519336aded3067e5034831dadf3 --- includes/user/User.php | 2 + tests/phpunit/includes/user/UserTest.php | 51 ++++++++++++++++++++++++ 2 files changed, 53 insertions(+) diff --git a/includes/user/User.php b/includes/user/User.php index d6523a7f3c..47d75338bb 100644 --- a/includes/user/User.php +++ b/includes/user/User.php @@ -1871,7 +1871,9 @@ class User implements IDBAccessObject, UserIdentity { $this->mHideName = $block->mHideName; $this->mAllowUsertalk = !$block->prevents( 'editownusertalk' ); } else { + $this->mBlock = null; $this->mBlockedby = ''; + $this->mBlockreason = ''; $this->mHideName = 0; $this->mAllowUsertalk = false; } diff --git a/tests/phpunit/includes/user/UserTest.php b/tests/phpunit/includes/user/UserTest.php index c225ba5b8c..ca83d66833 100644 --- a/tests/phpunit/includes/user/UserTest.php +++ b/tests/phpunit/includes/user/UserTest.php @@ -1142,4 +1142,55 @@ class UserTest extends MediaWikiTestCase { } catch ( InvalidArgumentException $ex ) { } } + + /** + * @covers User::getBlockedStatus + * @covers User::getBlock + * @covers User::blockedBy + * @covers User::blockedFor + * @covers User::isHidden + * @covers User::isBlockedFrom + */ + public function testBlockInstanceCache() { + // First, check the user isn't blocked + $user = $this->getMutableTestUser()->getUser(); + $ut = Title::makeTitle( NS_USER_TALK, $user->getName() ); + $this->assertNull( $user->getBlock( false ), 'sanity check' ); + $this->assertSame( '', $user->blockedBy(), 'sanity check' ); + $this->assertSame( '', $user->blockedFor(), 'sanity check' ); + $this->assertFalse( (bool)$user->isHidden(), 'sanity check' ); + $this->assertFalse( $user->isBlockedFrom( $ut ), 'sanity check' ); + + // Block the user + $blocker = $this->getTestSysop()->getUser(); + $block = new Block( [ + 'hideName' => true, + 'allowUsertalk' => false, + 'reason' => 'Because', + ] ); + $block->setTarget( $user ); + $block->setBlocker( $blocker ); + $res = $block->insert(); + $this->assertTrue( (bool)$res['id'], 'sanity check: Failed to insert block' ); + + // Clear cache and confirm it loaded the block properly + $user->clearInstanceCache(); + $this->assertInstanceOf( Block::class, $user->getBlock( false ) ); + $this->assertSame( $blocker->getName(), $user->blockedBy() ); + $this->assertSame( 'Because', $user->blockedFor() ); + $this->assertTrue( (bool)$user->isHidden() ); + $this->assertTrue( $user->isBlockedFrom( $ut ) ); + + // Unblock + $block->delete(); + + // Clear cache and confirm it loaded the not-blocked properly + $user->clearInstanceCache(); + $this->assertNull( $user->getBlock( false ) ); + $this->assertSame( '', $user->blockedBy() ); + $this->assertSame( '', $user->blockedFor() ); + $this->assertFalse( (bool)$user->isHidden() ); + $this->assertFalse( $user->isBlockedFrom( $ut ) ); + } + } -- 2.20.1