From 43112b60dafed83fe8ceb948614fcb5662aa4b4d Mon Sep 17 00:00:00 2001 From: =?utf8?q?Gerg=C5=91=20Tisza?= Date: Wed, 27 Jul 2016 01:44:53 +0000 Subject: [PATCH] Add User::findUsersByGroup() Needed by Iee6e0074d64. Change-Id: Idbaf2102410f82343ad38ff51ccb7ab70b15e654 --- includes/user/User.php | 38 ++++++++++++++++++++++++ tests/phpunit/includes/user/UserTest.php | 33 ++++++++++++++++++++ 2 files changed, 71 insertions(+) diff --git a/includes/user/User.php b/includes/user/User.php index a774aba4d9..39507af97a 100644 --- a/includes/user/User.php +++ b/includes/user/User.php @@ -911,6 +911,44 @@ class User implements IDBAccessObject { return true; } + /** + * Return the users who are members of the given group(s). In case of multiple groups, + * users who are members of at least one of them are returned. + * + * @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 + * @return UserArrayFromResult + */ + public static function findUsersByGroup( $groups, $limit = 5000, $after = null ) { + if ( $groups === [] ) { + return UserArrayFromResult::newFromIDs( [] ); + } + + $groups = array_unique( (array)$groups ); + $limit = min( 5000, $limit ); + + $conds = [ 'ug_group' => $groups ]; + if ( $after !== null ) { + $conds[] = 'ug_user > ' . (int)$after; + } + + $dbr = wfGetDB( DB_SLAVE ); + $ids = $dbr->selectFieldValues( + 'user_groups', + 'ug_user', + $conds, + __METHOD__, + [ + 'DISTINCT' => true, + 'ORDER BY' => 'ug_user', + 'LIMIT' => $limit, + ] + ) ?: []; + return UserArray::newFromIDs( $ids ); + } + /** * Usernames which fail to pass this function will be blocked * from new account registrations, but may be used internally diff --git a/tests/phpunit/includes/user/UserTest.php b/tests/phpunit/includes/user/UserTest.php index 801ab9179b..beb5e78259 100644 --- a/tests/phpunit/includes/user/UserTest.php +++ b/tests/phpunit/includes/user/UserTest.php @@ -451,4 +451,37 @@ class UserTest extends MediaWikiTestCase { $this->assertGreaterThan( $touched, $user->getDBTouched(), "user_touched increased with casOnTouched() #2" ); } + + /** + * @covers User::findUsersByGroup + */ + public function testFindUsersByGroup() { + $users = User::findUsersByGroup( [] ); + $this->assertEquals( 0, iterator_count( $users ) ); + + $users = User::findUsersByGroup( 'foo' ); + $this->assertEquals( 0, iterator_count( $users ) ); + + $user = $this->getMutableTestUser( [ 'foo' ] )->getUser(); + $users = User::findUsersByGroup( 'foo' ); + $this->assertEquals( 1, iterator_count( $users ) ); + $users->rewind(); + $this->assertTrue( $user->equals( $users->current() ) ); + + // arguments have OR relationship + $user2 = $this->getMutableTestUser( [ 'bar' ] )->getUser(); + $users = User::findUsersByGroup( [ 'foo', 'bar' ] ); + $this->assertEquals( 2, iterator_count( $users ) ); + $users->rewind(); + $this->assertTrue( $user->equals( $users->current() ) ); + $users->next(); + $this->assertTrue( $user2->equals( $users->current() ) ); + + // users are not duplicated + $user = $this->getMutableTestUser( [ 'baz', 'boom' ] )->getUser(); + $users = User::findUsersByGroup( [ 'baz', 'boom' ] ); + $this->assertEquals( 1, iterator_count( $users ) ); + $users->rewind(); + $this->assertTrue( $user->equals( $users->current() ) ); + } } -- 2.20.1