4 use Wikimedia\Assert\Assert;
62 return $this->loadBalancer->getConnection(
DB_SLAVE, [
'watchlist' ] );
70 $this->loadBalancer->reuseConnection( $connection );
120 'includeFields' => [],
121 'namespaceIds' => [],
123 'allRevisions' =>
false,
124 'usedInGenerator' =>
false
130 '$options[\'rcTypes\']',
131 'must be an array containing only: RC_EDIT, RC_NEW, RC_LOG, RC_EXTERNAL and/or RC_CATEGORIZE'
134 !isset(
$options[
'dir'] ) || in_array(
$options[
'dir'], [ self::DIR_OLDER, self::DIR_NEWER ] ),
136 'must be DIR_OLDER or DIR_NEWER'
142 'must be provided when providing any of options: start, end, startFrom'
146 || ( is_array(
$options[
'startFrom'] ) && count(
$options[
'startFrom'] ) === 2 ),
147 '$options[\'startFrom\']',
148 'must be a two-element array'
150 if ( array_key_exists(
'watchlistOwner',
$options ) ) {
151 Assert::parameterType(
154 '$options[\'watchlistOwner\']'
157 isset(
$options[
'watchlistOwnerToken'] ),
158 '$options[\'watchlistOwnerToken\']',
159 'must be provided when providing watchlistOwner option'
163 $tables = [
'recentchanges',
'watchlist' ];
187 foreach (
$res as $row ) {
191 new TitleValue( (
int)$row->rc_namespace, $row->rc_title ),
192 $row->wl_notificationtimestamp
227 $options += [
'namespaceIds' => [] ];
230 !isset(
$options[
'sort'] ) || in_array(
$options[
'sort'], [ self::SORT_ASC, self::SORT_DESC ] ),
231 '$options[\'sort\']',
232 'must be SORT_ASC or SORT_DESC'
235 !isset(
$options[
'filter'] ) || in_array(
236 $options[
'filter'], [ self::FILTER_CHANGED, self::FILTER_NOT_CHANGED ]
238 '$options[\'filter\']',
239 'must be FILTER_CHANGED or FILTER_NOT_CHANGED'
244 '$options[\'sort\']',
245 'must be provided if any of "from", "until", "startFrom" options is provided'
255 [
'wl_namespace',
'wl_title',
'wl_notificationtimestamp' ],
264 foreach (
$res as $row ) {
268 new TitleValue( (
int)$row->wl_namespace, $row->wl_title ),
269 $row->wl_notificationtimestamp
273 return $watchedItems;
279 $allFields = get_object_vars( $row );
280 $rcKeys = array_filter(
281 array_keys( $allFields ),
283 return substr( $key, 0, 3 ) ===
'rc_';
286 return array_intersect_key( $allFields, array_flip( $rcKeys ) );
297 'wl_notificationtimestamp'
305 if ( $options[
'usedInGenerator'] ) {
306 if ( $options[
'allRevisions'] ) {
307 $rcIdFields = [
'rc_this_oldid' ];
309 $rcIdFields = [
'rc_cur_id' ];
312 $fields = array_merge( $fields, $rcIdFields );
314 if ( in_array( self::INCLUDE_FLAGS, $options[
'includeFields'] ) ) {
315 $fields = array_merge( $fields, [
'rc_type',
'rc_minor',
'rc_bot' ] );
317 if ( in_array( self::INCLUDE_USER, $options[
'includeFields'] ) ) {
318 $fields[] =
'rc_user_text';
320 if ( in_array( self::INCLUDE_USER_ID, $options[
'includeFields'] ) ) {
321 $fields[] =
'rc_user';
323 if ( in_array( self::INCLUDE_COMMENT, $options[
'includeFields'] ) ) {
324 $fields[] =
'rc_comment';
326 if ( in_array( self::INCLUDE_PATROL_INFO, $options[
'includeFields'] ) ) {
327 $fields = array_merge( $fields, [
'rc_patrolled',
'rc_log_type' ] );
329 if ( in_array( self::INCLUDE_SIZES, $options[
'includeFields'] ) ) {
330 $fields = array_merge( $fields, [
'rc_old_len',
'rc_new_len' ] );
332 if ( in_array( self::INCLUDE_LOG_INFO, $options[
'includeFields'] ) ) {
333 $fields = array_merge( $fields, [
'rc_logid',
'rc_log_type',
'rc_log_action',
'rc_params' ] );
345 $conds = [
'wl_user' => $watchlistOwnerId ];
347 if ( !$options[
'allRevisions'] ) {
349 [
'rc_this_oldid=page_latest',
'rc_type=' .
RC_LOG ],
354 if ( $options[
'namespaceIds'] ) {
355 $conds[
'wl_namespace'] = array_map(
'intval', $options[
'namespaceIds'] );
358 if ( array_key_exists(
'rcTypes', $options ) ) {
359 $conds[
'rc_type'] = array_map(
'intval', $options[
'rcTypes'] );
362 $conds = array_merge(
369 if ( !isset( $options[
'start'] ) && !isset( $options[
'end'] ) ) {
370 if ( $db->
getType() ===
'mysql' ) {
372 $conds[] =
"rc_timestamp > ''";
379 if ( $deletedPageLogCond ) {
380 $conds[] = $deletedPageLogCond;
383 if ( array_key_exists(
'startFrom', $options ) ) {
391 if ( array_key_exists(
'watchlistOwner', $options ) ) {
393 $watchlistOwner = $options[
'watchlistOwner'];
394 $ownersToken = $watchlistOwner->getOption(
'watchlisttoken' );
395 $token = $options[
'watchlistOwnerToken'];
396 if ( $ownersToken ==
'' || !hash_equals( $ownersToken, $token ) ) {
398 'Incorrect watchlist token provided -- please set a correct token in Special:Preferences',
402 return $watchlistOwner->getId();
404 return $user->
getId();
410 if ( in_array( self::FILTER_MINOR, $options[
'filters'] ) ) {
411 $conds[] =
'rc_minor != 0';
412 } elseif ( in_array( self::FILTER_NOT_MINOR, $options[
'filters'] ) ) {
413 $conds[] =
'rc_minor = 0';
416 if ( in_array( self::FILTER_BOT, $options[
'filters'] ) ) {
417 $conds[] =
'rc_bot != 0';
418 } elseif ( in_array( self::FILTER_NOT_BOT, $options[
'filters'] ) ) {
419 $conds[] =
'rc_bot = 0';
422 if ( in_array( self::FILTER_ANON, $options[
'filters'] ) ) {
423 $conds[] =
'rc_user = 0';
424 } elseif ( in_array( self::FILTER_NOT_ANON, $options[
'filters'] ) ) {
425 $conds[] =
'rc_user != 0';
431 if ( in_array( self::FILTER_PATROLLED, $options[
'filters'] ) ) {
432 $conds[] =
'rc_patrolled != 0';
433 } elseif ( in_array( self::FILTER_NOT_PATROLLED, $options[
'filters'] ) ) {
434 $conds[] =
'rc_patrolled = 0';
438 if ( in_array( self::FILTER_UNREAD, $options[
'filters'] ) ) {
439 $conds[] =
'rc_timestamp >= wl_notificationtimestamp';
440 } elseif ( in_array( self::FILTER_NOT_UNREAD, $options[
'filters'] ) ) {
442 $conds[] =
'wl_notificationtimestamp IS NULL OR rc_timestamp < wl_notificationtimestamp';
449 if ( !isset( $options[
'start'] ) && ! isset( $options[
'end'] ) ) {
455 if ( isset( $options[
'start'] ) ) {
456 $after = $options[
'dir'] === self::DIR_OLDER ?
'<=' :
'>=';
457 $conds[] =
'rc_timestamp ' . $after .
' ' . $db->
addQuotes( $options[
'start'] );
459 if ( isset( $options[
'end'] ) ) {
460 $before = $options[
'dir'] === self::DIR_OLDER ?
'>=' :
'<=';
461 $conds[] =
'rc_timestamp ' . $before .
' ' . $db->
addQuotes( $options[
'end'] );
468 if ( !array_key_exists(
'onlyByUser', $options ) && !array_key_exists(
'notByUser', $options ) ) {
474 if ( array_key_exists(
'onlyByUser', $options ) ) {
475 $conds[
'rc_user_text'] = $options[
'onlyByUser'];
476 } elseif ( array_key_exists(
'notByUser', $options ) ) {
477 $conds[] =
'rc_user_text != ' . $db->
addQuotes( $options[
'notByUser'] );
482 if ( !$user->
isAllowed(
'deletedhistory' ) ) {
484 } elseif ( !$user->
isAllowedAny(
'suppressrevision',
'viewsuppressed' ) ) {
488 $conds[] = $db->
bitAnd(
'rc_deleted', $bitmask ) .
" != $bitmask";
498 if ( !$user->
isAllowed(
'deletedhistory' ) ) {
500 } elseif ( !$user->
isAllowedAny(
'suppressrevision',
'viewsuppressed' ) ) {
506 $db->
bitAnd(
'rc_deleted', $bitmask ) .
" != $bitmask",
513 $op = $options[
'dir'] === self::DIR_OLDER ?
'<' :
'>';
514 list( $rcTimestamp, $rcId ) = $options[
'startFrom'];
519 "rc_timestamp $op $rcTimestamp",
522 "rc_timestamp = $rcTimestamp",
533 $conds = [
'wl_user' => $user->
getId() ];
534 if ( $options[
'namespaceIds'] ) {
535 $conds[
'wl_namespace'] = array_map(
'intval', $options[
'namespaceIds'] );
537 if ( isset( $options[
'filter'] ) ) {
538 $filter = $options[
'filter'];
539 if ( $filter === self::FILTER_CHANGED ) {
540 $conds[] =
'wl_notificationtimestamp IS NOT NULL';
542 $conds[] =
'wl_notificationtimestamp IS NULL';
546 if ( isset( $options[
'from'] ) ) {
547 $op = $options[
'sort'] === self::SORT_ASC ?
'>' :
'<';
550 if ( isset( $options[
'until'] ) ) {
551 $op = $options[
'sort'] === self::SORT_ASC ?
'<' :
'>';
554 if ( isset( $options[
'startFrom'] ) ) {
555 $op = $options[
'sort'] === self::SORT_ASC ?
'>' :
'<';
590 if ( array_key_exists(
'dir', $options ) ) {
591 $sort = $options[
'dir'] === self::DIR_OLDER ?
' DESC' :
'';
592 $dbOptions[
'ORDER BY'] = [
'rc_timestamp' .
$sort,
'rc_id' .
$sort ];
595 if ( array_key_exists(
'limit', $options ) ) {
596 $dbOptions[
'LIMIT'] = (int)$options[
'limit'];
604 if ( array_key_exists(
'sort', $options ) ) {
605 $dbOptions[
'ORDER BY'] = [
606 "wl_namespace {$options['sort']}",
607 "wl_title {$options['sort']}"
609 if ( count( $options[
'namespaceIds'] ) === 1 ) {
610 $dbOptions[
'ORDER BY'] =
"wl_title {$options['sort']}";
613 if ( array_key_exists(
'limit', $options ) ) {
614 $dbOptions[
'LIMIT'] = (int)$options[
'limit'];
621 'watchlist' => [
'INNER JOIN',
623 'wl_namespace=rc_namespace',
628 if ( !$options[
'allRevisions'] ) {
629 $joinConds[
'page'] = [
'LEFT JOIN',
'rc_cur_id=page_id' ];
getWatchedItemsWithRCInfoQueryFields(array $options)
getWatchedItemsWithRecentChangeInfo(User $user, array $options=[])
deferred txt A few of the database updates required by various functions here can be deferred until after the result page is displayed to the user For updating the view updating the linked to tables after a etc PHP does not yet have any way to tell the server to actually return and disconnect while still running these but it might have such a feature in the future We handle these by creating a deferred update object and putting those objects on a global list
the array() calling protocol came about after MediaWiki 1.4rc1.
getWatchedItemsForUser(User $user, array $options=[])
For simple listing of user's watchlist items, see WatchedItemStore::getWatchedItemsForUser.
getFromUntilTargetConds(DatabaseBase $db, LinkTarget $target, $op)
Creates a query condition part for getting only items before or after the given link target (while or...
getWatchedItemsForUserQueryDbOptions(array $options)
getStartEndConds(DatabaseBase $db, array $options)
processing should stop and the error should be shown to the user * false
Apache License January AND DISTRIBUTION Definitions License shall mean the terms and conditions for use
isAllowedAny()
Check if user is allowed to access a feature / make an action.
LoadBalancer $loadBalancer
getWatchedItemsWithRCInfoQueryDbOptions(array $options)
Represents a page (or page fragment) title within MediaWiki.
getWatchedItemsWithRCInfoQueryJoinConds(array $options)
makeList($a, $mode=LIST_COMMA)
Makes an encoded list of strings from an array.
getStartFromConds(DatabaseBase $db, array $options)
getExtraDeletedPageLogEntryRelatedCond(DatabaseBase $db, User $user)
getUserRelatedConds(DatabaseBase $db, User $user, array $options)
getType()
Get the type of the DBMS, as it appears in $wgDBtype.
const INCLUDE_PATROL_INFO
this hook is for auditing only RecentChangesLinked and Watchlist RecentChangesLinked and Watchlist e g Watchlist & $tables
The User object encapsulates all of the user-specific settings (user_id, name, rights, email address, options, last login time).
Database load balancing object.
timestamp($ts=0)
Convert a timestamp in one of the formats accepted by wfTimestamp() to the format used for inserting ...
bitAnd($fieldLeft, $fieldRight)
isAllowed($action= '')
Internal mechanics of testing a permission.
isAnon()
Get whether the user is anonymous.
this hook is for auditing only RecentChangesLinked and Watchlist RecentChangesLinked and Watchlist e g Watchlist removed from all revisions and log entries to which it was applied This gives extensions a chance to take it off their books as the deletion has already been partly carried out by this point or something similar the user will be unable to create the tag set and then return false from the hook function Ensure you consume the ChangeTagAfterDelete hook to carry out custom deletion actions as context called by AbstractContent::getParserOutput May be used to override the normal model specific rendering of page content as context as context $options
getWatchedItemsWithRCInfoQueryFilterConds(User $user, array $options)
const FILTER_NOT_PATROLLED
Representation of a pair of user and title for watchlist entries.
addQuotes($s)
Adds quotes and backslashes.
This document is intended to provide useful advice for parties seeking to redistribute MediaWiki to end users It s targeted particularly at maintainers for Linux since it s been observed that distribution packages of MediaWiki often break We ve consistently had to recommend that users seeking support use official tarballs instead of their distribution s and this often solves whatever problem the user is having It would be nice if this could such as
please add to it if you re going to add events to the MediaWiki code where normally authentication against an external auth plugin would be creating a local account $user
useRCPatrol()
Check whether to enable recent changes patrol features for this user.
Database abstraction object.
injection txt This is an overview of how MediaWiki makes use of dependency injection The design described here grew from the discussion of RFC T384 The term dependency this means that anything an object needs to operate should be injected from the the object itself should only know narrow no concrete implementation of the logic it relies on The requirement to inject everything typically results in an architecture that based on two main types of and essentially stateless service objects that use other service objects to operate on the value objects As of the beginning MediaWiki is only starting to use the DI approach Much of the code still relies on global state or direct resulting in a highly cyclical dependency which acts as the top level factory for services in MediaWiki which can be used to gain access to default instances of various services MediaWikiServices however also allows new services to be defined and default services to be redefined Services are defined or redefined by providing a callback the instantiator that will return a new instance of the service When it will create an instance of MediaWikiServices and populate it with the services defined in the files listed by thereby bootstrapping the DI framework Per $wgServiceWiringFiles lists includes ServiceWiring php
getWatchlistOwnerId(User $user, array $options)
getRecentChangeFieldsFromRow(stdClass $row)
getId()
Get the user's ID.
you have access to all of the normal MediaWiki so you can get a DB use the etc For full docs on the Maintenance class
getWatchedItemsWithRCInfoQueryConds(DatabaseBase $db, User $user, array $options)
useNPPatrol()
Check whether to enable new pages patrol features for this user.
reuseConnection(DatabaseBase $connection)
__construct(LoadBalancer $loadBalancer)
This exception will be thrown when dieUsage is called to stop module execution.
getWatchedItemsForUserQueryConds(DatabaseBase $db, User $user, array $options)