Page Menu
Home
WickedGov Phorge
Search
Configure Global Search
Log In
Files
F4072305
UserLocator.php
No One
Temporary
Actions
Download File
Edit File
Delete File
View Transforms
Subscribe
Flag For Later
Award Token
Size
5 KB
Referenced Files
None
Subscribers
None
UserLocator.php
View Options
<?php
namespace
MediaWiki\Extension\Notifications
;
use
BatchRowIterator
;
use
Iterator
;
use
MediaWiki\Extension\Notifications\Iterator\CallbackIterator
;
use
MediaWiki\Extension\Notifications\Model\Event
;
use
MediaWiki\MediaWikiServices
;
use
MediaWiki\User\User
;
use
RecursiveIteratorIterator
;
class
UserLocator
{
/**
* Return all users watching the event title.
*
* The echo job queue must be enabled to prevent timeouts submitting to
* heavily watched pages when this is used.
*
* @param Event $event
* @param int $batchSize
* @return User[]|Iterator<User>
*/
public
static
function
locateUsersWatchingTitle
(
Event
$event
,
$batchSize
=
500
)
{
$title
=
$event
->
getTitle
();
if
(
!
$title
)
{
return
[];
}
$provider
=
MediaWikiServices
::
getInstance
()->
getConnectionProvider
();
$batchRowIt
=
new
BatchRowIterator
(
$provider
->
getReplicaDatabase
(
false
,
'watchlist'
),
/* $table = */
'watchlist'
,
/* $primaryKeys = */
[
'wl_user'
],
$batchSize
);
$batchRowIt
->
addConditions
(
[
'wl_namespace'
=>
$title
->
getNamespace
(),
'wl_title'
=>
$title
->
getDBkey
(),
]
);
$batchRowIt
->
setCaller
(
__METHOD__
);
// flatten the result into a stream of rows
$recursiveIt
=
new
RecursiveIteratorIterator
(
$batchRowIt
);
// add callback to convert user id to user objects
$echoCallbackIt
=
new
CallbackIterator
(
$recursiveIt
,
static
function
(
$row
)
{
return
User
::
newFromId
(
$row
->
wl_user
);
}
);
return
$echoCallbackIt
;
}
/**
* If the event occurred on the talk page of a registered
* user return that user.
*
* @param Event $event
* @return User[]
*/
public
static
function
locateTalkPageOwner
(
Event
$event
)
{
$title
=
$event
->
getTitle
();
if
(
!
$title
||
$title
->
getNamespace
()
!==
NS_USER_TALK
)
{
return
[];
}
$user
=
User
::
newFromName
(
$title
->
getDBkey
()
);
if
(
$user
&&
$user
->
isRegistered
()
)
{
return
[
$user
->
getId
()
=>
$user
];
}
return
[];
}
/**
* If the event occurred on the user page of a registered
* user return that user.
*
* @param Event $event
* @return User[]
*/
public
static
function
locateUserPageOwner
(
Event
$event
)
{
$title
=
$event
->
getTitle
();
if
(
!
$title
||
!
$title
->
inNamespace
(
NS_USER
)
)
{
return
[];
}
$user
=
User
::
newFromName
(
$title
->
getDBkey
()
);
if
(
$user
&&
$user
->
isRegistered
()
)
{
return
[
$user
->
getId
()
=>
$user
];
}
return
[];
}
/**
* Return the event agent
*
* @param Event $event
* @return User[]
*/
public
static
function
locateEventAgent
(
Event
$event
)
{
$agent
=
$event
->
getAgent
();
if
(
$agent
&&
$agent
->
isRegistered
()
)
{
return
[
$agent
->
getId
()
=>
$agent
];
}
return
[];
}
/**
* Return the user that created the first revision of the
* associated title.
*
* @param Event $event
* @return User[]
*/
public
static
function
locateArticleCreator
(
Event
$event
)
{
$title
=
$event
->
getTitle
();
if
(
!
$title
||
$title
->
getArticleID
()
<=
0
)
{
return
[];
}
$user
=
self
::
getArticleAuthorByArticleId
(
$title
->
getArticleID
()
);
if
(
$user
)
{
// T318523: Don't send page-linked notifications for pages created by bot users.
if
(
$event
->
getType
()
===
'page-linked'
&&
$user
->
isBot
()
)
{
return
[];
}
return
[
$user
->
getId
()
=>
$user
];
}
return
[];
}
/**
* @param int $articleId
* @return User|null
*/
public
static
function
getArticleAuthorByArticleId
(
int
$articleId
):
?
User
{
$services
=
MediaWikiServices
::
getInstance
();
$dbr
=
$services
->
getConnectionProvider
()->
getReplicaDatabase
();
$revQuery
=
$services
->
getRevisionStore
()->
getQueryInfo
();
$res
=
$dbr
->
newSelectQueryBuilder
()
->
select
(
[
'rev_user'
=>
$revQuery
[
'fields'
][
'rev_user'
]
]
)
->
tables
(
$revQuery
[
'tables'
]
)
->
where
(
[
'rev_page'
=>
$articleId
]
)
->
orderBy
(
[
'rev_timestamp'
,
'rev_id'
]
)
->
joinConds
(
$revQuery
[
'joins'
]
)
->
caller
(
__METHOD__
)
->
fetchRow
();
if
(
!
$res
||
!
$res
->
rev_user
)
{
return
null
;
}
return
User
::
newFromId
(
$res
->
rev_user
);
}
/**
* Fetch user ids from the event extra data. Requires additional
* parameter. Example $wgEchoNotifications parameter:
*
* 'user-locators' => [ [ 'event-extra', 'mentions' ] ],
*
* The above will look in the 'mentions' parameter for a user id or
* array of user ids. It will return all these users as notification
* targets.
*
* @param Event $event
* @param string[] $keys one or more keys to check for user ids
* @return array<int,User>
*/
public
static
function
locateFromEventExtra
(
Event
$event
,
array
$keys
)
{
$users
=
[];
foreach
(
$keys
as
$key
)
{
$userIds
=
$event
->
getExtraParam
(
$key
);
if
(
!
$userIds
)
{
continue
;
}
if
(
!
is_array
(
$userIds
)
)
{
$userIds
=
[
$userIds
];
}
foreach
(
$userIds
as
$userId
)
{
// we shouldn't receive User instances, but allow
// it for backward compatability
if
(
$userId
instanceof
User
)
{
if
(
!
$userId
->
isRegistered
()
)
{
continue
;
}
$user
=
$userId
;
}
else
{
$user
=
User
::
newFromId
(
$userId
);
}
$users
[
$user
->
getId
()]
=
$user
;
}
}
return
$users
;
}
}
class_alias
(
UserLocator
::
class
,
'EchoUserLocator'
);
File Metadata
Details
Attached
Mime Type
text/x-php
Expires
Aug 17 2026, 07:24 (11 w, 3 d ago)
Storage Engine
local-disk
Storage Format
Raw Data
Storage Handle
39/bc/3f6bbea7a9543533675d446b5065
Default Alt Text
UserLocator.php (5 KB)
Attached To
Mode
rMWPROD MediaWiki Production
Attached
Detach File
Event Timeline
Log In to Comment