2014-07-31 02:31:47 +00:00
|
|
|
<?php
|
|
|
|
|
2023-04-28 09:58:56 +00:00
|
|
|
namespace MediaWiki\Extension\Notifications\Test;
|
|
|
|
|
2024-10-19 22:55:03 +00:00
|
|
|
use MediaWiki\Content\ContentHandler;
|
2022-11-02 21:34:17 +00:00
|
|
|
use MediaWiki\Extension\Notifications\Model\Event;
|
2022-11-12 07:19:00 +00:00
|
|
|
use MediaWiki\Extension\Notifications\UserLocator;
|
2023-04-28 09:58:56 +00:00
|
|
|
use MediaWiki\Title\Title;
|
2023-12-11 15:33:08 +00:00
|
|
|
use MediaWiki\User\User;
|
2023-04-28 09:58:56 +00:00
|
|
|
use MediaWikiIntegrationTestCase;
|
2022-11-02 21:34:17 +00:00
|
|
|
|
2014-07-31 02:31:47 +00:00
|
|
|
/**
|
2018-01-24 00:31:53 +00:00
|
|
|
* @group Database
|
2022-11-12 07:19:00 +00:00
|
|
|
* @covers \MediaWiki\Extension\Notifications\UserLocator
|
2014-07-31 02:31:47 +00:00
|
|
|
*/
|
2023-04-28 09:58:56 +00:00
|
|
|
class UserLocatorTest extends MediaWikiIntegrationTestCase {
|
2014-07-31 02:31:47 +00:00
|
|
|
|
2014-07-30 03:18:48 +00:00
|
|
|
public function testLocateUsersWatchingTitle() {
|
|
|
|
$title = Title::makeTitleSafe( NS_USER_TALK, 'Something_something_something' );
|
|
|
|
$key = $title->getDBkey();
|
|
|
|
|
|
|
|
for ( $i = 1000; $i < 1050; ++$i ) {
|
2016-12-05 18:51:07 +00:00
|
|
|
$rows[] = [
|
2014-07-30 03:18:48 +00:00
|
|
|
'wl_user' => $i,
|
|
|
|
'wl_namespace' => NS_USER_TALK,
|
|
|
|
'wl_title' => $key
|
2016-12-05 18:51:07 +00:00
|
|
|
];
|
2014-07-30 03:18:48 +00:00
|
|
|
}
|
2024-02-13 18:55:34 +00:00
|
|
|
|
2024-04-13 18:33:56 +00:00
|
|
|
$this->getDb()->newInsertQueryBuilder()
|
|
|
|
->insertInto( 'watchlist' )
|
|
|
|
->rows( $rows )
|
|
|
|
->caller( __METHOD__ )
|
|
|
|
->execute();
|
2014-07-30 03:18:48 +00:00
|
|
|
|
2022-11-02 21:34:17 +00:00
|
|
|
$event = $this->createMock( Event::class );
|
2022-09-29 13:41:35 +00:00
|
|
|
$event->method( 'getTitle' )
|
|
|
|
->willReturn( $title );
|
2014-07-30 03:18:48 +00:00
|
|
|
|
2022-11-12 07:19:00 +00:00
|
|
|
$it = UserLocator::locateUsersWatchingTitle( $event, 10 );
|
2019-10-23 10:28:30 +00:00
|
|
|
$this->assertCount( 50, $it );
|
2014-07-30 03:18:48 +00:00
|
|
|
// @todo assert more than one query was issued
|
|
|
|
}
|
2014-07-31 02:31:47 +00:00
|
|
|
|
2023-05-20 18:35:53 +00:00
|
|
|
public static function locateTalkPageOwnerProvider() {
|
2016-12-05 18:51:07 +00:00
|
|
|
return [
|
|
|
|
[
|
2014-07-31 02:31:47 +00:00
|
|
|
'Allows null event title',
|
|
|
|
// expected user id's
|
2023-05-20 18:35:53 +00:00
|
|
|
'empty',
|
2014-07-31 02:31:47 +00:00
|
|
|
// event title
|
|
|
|
null
|
2016-12-05 18:51:07 +00:00
|
|
|
],
|
2014-07-31 02:31:47 +00:00
|
|
|
|
2016-12-05 18:51:07 +00:00
|
|
|
[
|
2014-07-31 02:31:47 +00:00
|
|
|
'No users selected for non-user talk namespace',
|
|
|
|
// expected user id's
|
2023-05-20 18:35:53 +00:00
|
|
|
'empty',
|
2014-07-31 02:31:47 +00:00
|
|
|
// event title
|
|
|
|
Title::newMainPage(),
|
2016-12-05 18:51:07 +00:00
|
|
|
],
|
2014-07-31 02:31:47 +00:00
|
|
|
|
2016-12-05 18:51:07 +00:00
|
|
|
[
|
2014-07-31 02:31:47 +00:00
|
|
|
'Selects user from NS_USER_TALK',
|
2023-05-20 18:35:53 +00:00
|
|
|
// expected user id's
|
|
|
|
'user',
|
2016-12-05 18:51:07 +00:00
|
|
|
],
|
|
|
|
];
|
2014-07-31 02:31:47 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @dataProvider locateTalkPageOwnerProvider
|
|
|
|
*/
|
2024-10-26 13:05:00 +00:00
|
|
|
public function testLocateTalkPageOwner( $message, $expectMode, ?Title $title = null ) {
|
2023-05-20 18:35:53 +00:00
|
|
|
if ( $expectMode === 'user' ) {
|
|
|
|
$user = $this->getTestUser()->getUser();
|
|
|
|
$user->addToDatabase();
|
|
|
|
$expect = [ $user->getId() ];
|
|
|
|
$title = $user->getTalkPage();
|
|
|
|
} else {
|
|
|
|
$expect = [];
|
2014-07-31 02:31:47 +00:00
|
|
|
}
|
2022-11-02 21:34:17 +00:00
|
|
|
$event = $this->createMock( Event::class );
|
2022-09-29 13:41:35 +00:00
|
|
|
$event->method( 'getTitle' )
|
|
|
|
->willReturn( $title );
|
2014-07-31 02:31:47 +00:00
|
|
|
|
2022-11-12 07:19:00 +00:00
|
|
|
$users = UserLocator::locateTalkPageOwner( $event );
|
2014-07-31 02:31:47 +00:00
|
|
|
$this->assertEquals( $expect, array_keys( $users ), $message );
|
|
|
|
}
|
|
|
|
|
2023-05-20 18:35:53 +00:00
|
|
|
public static function locateArticleCreatorProvider() {
|
2016-12-05 18:51:07 +00:00
|
|
|
return [
|
2023-05-20 18:35:53 +00:00
|
|
|
[ 'Something' ],
|
2016-12-05 18:51:07 +00:00
|
|
|
];
|
2014-07-31 02:31:47 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @dataProvider locateArticleCreatorProvider
|
|
|
|
*/
|
2023-05-20 18:35:53 +00:00
|
|
|
public function testLocateArticleCreator( $message ) {
|
|
|
|
$user = $this->getTestUser()->getUser();
|
|
|
|
$user->addToDatabase();
|
|
|
|
$title = $user->getTalkPage();
|
2022-06-03 21:00:26 +00:00
|
|
|
$this->getServiceContainer()->getWikiPageFactory()->newFromTitle( $title )->doUserEditContent(
|
2014-07-31 02:31:47 +00:00
|
|
|
/* $content = */ ContentHandler::makeContent( 'content', $title ),
|
2021-06-24 04:54:45 +00:00
|
|
|
/* $user = */ $user,
|
|
|
|
/* $summary = */ 'summary'
|
2014-07-31 02:31:47 +00:00
|
|
|
);
|
|
|
|
|
2022-11-02 21:34:17 +00:00
|
|
|
$event = $this->createMock( Event::class );
|
2022-09-29 13:41:35 +00:00
|
|
|
$event->method( 'getTitle' )
|
|
|
|
->willReturn( $title );
|
|
|
|
$event->method( 'getAgent' )
|
|
|
|
->willReturn( User::newFromId( 123 ) );
|
2014-07-31 02:31:47 +00:00
|
|
|
|
2022-11-12 07:19:00 +00:00
|
|
|
$users = UserLocator::locateArticleCreator( $event );
|
2023-05-20 18:35:53 +00:00
|
|
|
$this->assertEquals( [ $user->getId() ], array_keys( $users ), $message );
|
2014-07-31 02:31:47 +00:00
|
|
|
}
|
|
|
|
|
2023-04-28 09:37:58 +00:00
|
|
|
public function testDontSendPageLinkedNotificationsForPagesCreatedByBotUsers() {
|
|
|
|
$botUser = $this->getTestUser( [ 'bot' ] )->getUser();
|
|
|
|
$botUser->addToDatabase();
|
|
|
|
$this->editPage( 'TestBotCreatedPage', 'Test', '', NS_MAIN, $botUser );
|
|
|
|
$this->editPage( 'SomeOtherPage', '[[TestBotCreatedPage]]' );
|
|
|
|
$event = $this->createMock( Event::class );
|
|
|
|
$event->method( 'getTitle' )
|
|
|
|
->willReturn( Title::newFromText( 'TestBotCreatedPage' ) );
|
|
|
|
$event->method( 'getAgent' )
|
|
|
|
->willReturn( User::newFromId( 123 ) );
|
|
|
|
$event->method( 'getType' )
|
|
|
|
->willReturn( 'page-linked' );
|
2024-06-12 18:31:47 +00:00
|
|
|
$this->assertEquals( [], UserLocator::locateArticleCreator( $event ) );
|
2023-04-28 09:37:58 +00:00
|
|
|
|
|
|
|
$normalUser = $this->getTestUser()->getUser();
|
|
|
|
$normalUser->addToDatabase();
|
|
|
|
$this->editPage( 'NormalCreatedPage', 'Test', '', NS_MAIN, $normalUser );
|
|
|
|
$this->editPage( 'AnotherPage', '[[NormalCreatedPage]]' );
|
|
|
|
$event = $this->createMock( Event::class );
|
|
|
|
$event->method( 'getTitle' )
|
|
|
|
->willReturn( Title::newFromText( 'NormalCreatedPage' ) );
|
|
|
|
$event->method( 'getAgent' )
|
|
|
|
->willReturn( User::newFromId( 456 ) );
|
|
|
|
$event->method( 'getType' )
|
|
|
|
->willReturn( 'page-linked' );
|
|
|
|
$this->assertEquals(
|
|
|
|
$normalUser->getUser()->getId(),
|
2024-06-12 18:31:47 +00:00
|
|
|
array_key_first( UserLocator::locateArticleCreator( $event ) )
|
2023-04-28 09:37:58 +00:00
|
|
|
);
|
|
|
|
}
|
|
|
|
|
2014-07-31 02:31:47 +00:00
|
|
|
public static function locateEventAgentProvider() {
|
2016-12-05 18:51:07 +00:00
|
|
|
return [
|
|
|
|
[
|
2014-07-31 02:31:47 +00:00
|
|
|
'Null event agent returns no users',
|
|
|
|
// expected result user id's
|
2016-12-05 18:51:07 +00:00
|
|
|
[],
|
2014-07-31 02:31:47 +00:00
|
|
|
// event agent
|
|
|
|
null,
|
2016-12-05 18:51:07 +00:00
|
|
|
],
|
2014-07-31 02:31:47 +00:00
|
|
|
|
2016-12-05 18:51:07 +00:00
|
|
|
[
|
2014-07-31 02:31:47 +00:00
|
|
|
'Anonymous event agent returns no users',
|
|
|
|
// expected result user id's
|
2016-12-05 18:51:07 +00:00
|
|
|
[],
|
2014-07-31 02:31:47 +00:00
|
|
|
// event agent
|
2022-11-12 06:37:37 +00:00
|
|
|
User::newFromName( '4.5.6.7', false ),
|
2016-12-05 18:51:07 +00:00
|
|
|
],
|
2014-07-31 02:31:47 +00:00
|
|
|
|
2016-12-05 18:51:07 +00:00
|
|
|
[
|
2014-07-31 02:31:47 +00:00
|
|
|
'Registed event agent returned as user',
|
|
|
|
// expected result user id's
|
2016-12-05 18:51:07 +00:00
|
|
|
[ 42 ],
|
2014-07-31 02:31:47 +00:00
|
|
|
// event agent
|
|
|
|
User::newFromId( 42 ),
|
2016-12-05 18:51:07 +00:00
|
|
|
],
|
|
|
|
];
|
2014-07-31 02:31:47 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @dataProvider locateEventAgentProvider
|
|
|
|
*/
|
2024-10-26 13:05:00 +00:00
|
|
|
public function testLocateEventAgent( $message, $expect, ?User $agent = null ) {
|
2022-11-02 21:34:17 +00:00
|
|
|
$event = $this->createMock( Event::class );
|
2022-09-29 13:41:35 +00:00
|
|
|
$event->method( 'getAgent' )
|
|
|
|
->willReturn( $agent );
|
2014-07-31 02:31:47 +00:00
|
|
|
|
2022-11-12 07:19:00 +00:00
|
|
|
$users = UserLocator::locateEventAgent( $event );
|
2014-07-31 02:31:47 +00:00
|
|
|
$this->assertEquals( $expect, array_keys( $users ), $message );
|
|
|
|
}
|
|
|
|
|
2023-05-20 18:35:53 +00:00
|
|
|
public static function locateFromEventExtraProvider() {
|
2016-12-05 18:51:07 +00:00
|
|
|
return [
|
|
|
|
[
|
2014-07-31 02:31:47 +00:00
|
|
|
'Event without extra data returns empty result',
|
|
|
|
// expected user list
|
2016-12-05 18:51:07 +00:00
|
|
|
[],
|
2014-07-31 02:31:47 +00:00
|
|
|
// event extra data
|
2016-12-05 18:51:07 +00:00
|
|
|
[],
|
2014-07-31 02:31:47 +00:00
|
|
|
// extra keys to get ids from
|
2016-12-05 18:51:07 +00:00
|
|
|
[ 'foo' ],
|
|
|
|
],
|
2014-07-31 02:31:47 +00:00
|
|
|
|
2016-12-05 18:51:07 +00:00
|
|
|
[
|
2014-07-31 02:31:47 +00:00
|
|
|
'Event with specified extra data returns expected result',
|
|
|
|
// expected user list
|
2016-12-05 18:51:07 +00:00
|
|
|
[ 123 ],
|
2014-07-31 02:31:47 +00:00
|
|
|
// event extra data
|
2016-12-05 18:51:07 +00:00
|
|
|
[ 'foo' => 123 ],
|
2014-07-31 02:31:47 +00:00
|
|
|
// extra keys to get ids from
|
2016-12-05 18:51:07 +00:00
|
|
|
[ 'foo' ],
|
|
|
|
],
|
2014-07-31 02:31:47 +00:00
|
|
|
|
2016-12-05 18:51:07 +00:00
|
|
|
[
|
2014-07-31 02:31:47 +00:00
|
|
|
'Accepts User objects instead of user ids',
|
|
|
|
// expected user list
|
2016-12-05 18:51:07 +00:00
|
|
|
[ 123 ],
|
2014-07-31 02:31:47 +00:00
|
|
|
// event extra data
|
2016-12-05 18:51:07 +00:00
|
|
|
[ 'foo' => User::newFromId( 123 ) ],
|
2014-07-31 02:31:47 +00:00
|
|
|
// extra keys to get ids from
|
2016-12-05 18:51:07 +00:00
|
|
|
[ 'foo' ],
|
|
|
|
],
|
2014-07-31 02:31:47 +00:00
|
|
|
|
2016-12-05 18:51:07 +00:00
|
|
|
[
|
2014-07-31 02:31:47 +00:00
|
|
|
'Allows inner key to be array of ids',
|
|
|
|
// expected user list
|
2016-12-05 18:51:07 +00:00
|
|
|
[ 123, 321 ],
|
2014-07-31 02:31:47 +00:00
|
|
|
// event extra data
|
2016-12-05 18:51:07 +00:00
|
|
|
[ 'foo' => [ 123, 321 ] ],
|
2014-07-31 02:31:47 +00:00
|
|
|
// extra keys to get ids from
|
2016-12-05 18:51:07 +00:00
|
|
|
[ 'foo' ],
|
|
|
|
],
|
2014-07-31 02:31:47 +00:00
|
|
|
|
2016-12-05 18:51:07 +00:00
|
|
|
[
|
2014-07-31 02:31:47 +00:00
|
|
|
'Empty inner array causes no error',
|
|
|
|
// expected user list
|
2016-12-05 18:51:07 +00:00
|
|
|
[],
|
2014-07-31 02:31:47 +00:00
|
|
|
// event extra data
|
2016-12-05 18:51:07 +00:00
|
|
|
[ 'foo' => [] ],
|
2014-07-31 02:31:47 +00:00
|
|
|
// extra keys to get ids from
|
2016-12-05 18:51:07 +00:00
|
|
|
[ 'foo' ],
|
|
|
|
],
|
2014-07-31 02:31:47 +00:00
|
|
|
|
2016-12-05 18:51:07 +00:00
|
|
|
[
|
2014-07-31 02:31:47 +00:00
|
|
|
'Accepts User object at inner level',
|
|
|
|
// expected user list
|
2016-12-05 18:51:07 +00:00
|
|
|
[ 123 ],
|
2014-07-31 02:31:47 +00:00
|
|
|
// event extra data
|
2016-12-05 18:51:07 +00:00
|
|
|
[ 'foo' => [ User::newFromId( 123 ) ] ],
|
2014-07-31 02:31:47 +00:00
|
|
|
// extra keys to get ids from
|
2016-12-05 18:51:07 +00:00
|
|
|
[ 'foo' ],
|
|
|
|
],
|
2014-07-31 02:31:47 +00:00
|
|
|
|
2016-12-05 18:51:07 +00:00
|
|
|
];
|
2014-07-31 02:31:47 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @dataProvider locateFromEventExtraProvider
|
|
|
|
*/
|
|
|
|
public function testLocateFromEventExtra( $message, $expect, array $extra, array $keys ) {
|
2022-11-02 21:34:17 +00:00
|
|
|
$event = $this->createMock( Event::class );
|
2022-09-29 13:41:35 +00:00
|
|
|
$event->method( 'getExtra' )
|
|
|
|
->willReturn( $extra );
|
|
|
|
$event->method( 'getExtraParam' )
|
2022-11-12 06:37:37 +00:00
|
|
|
->willReturnMap( self::arrayToValueMap( $extra ) );
|
2014-07-31 02:31:47 +00:00
|
|
|
|
2022-11-12 07:19:00 +00:00
|
|
|
$users = UserLocator::locateFromEventExtra( $event, $keys );
|
2014-07-31 02:31:47 +00:00
|
|
|
$this->assertEquals( $expect, array_keys( $users ), $message );
|
|
|
|
}
|
|
|
|
|
|
|
|
protected static function arrayToValueMap( array $array ) {
|
2016-12-05 18:51:07 +00:00
|
|
|
$result = [];
|
2014-07-31 02:31:47 +00:00
|
|
|
foreach ( $array as $key => $value ) {
|
2022-11-02 21:34:17 +00:00
|
|
|
// Event::getExtraParam second argument defaults to null
|
2016-12-05 18:51:07 +00:00
|
|
|
$result[] = [ $key, null, $value ];
|
2014-07-31 02:31:47 +00:00
|
|
|
}
|
2015-10-01 13:48:52 +00:00
|
|
|
|
2014-07-31 02:31:47 +00:00
|
|
|
return $result;
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|