summaryrefslogtreecommitdiff
path: root/includes/changes
diff options
context:
space:
mode:
Diffstat (limited to 'includes/changes')
-rw-r--r--includes/changes/ChangesFeed.php240
-rw-r--r--includes/changes/ChangesList.php250
-rw-r--r--includes/changes/EnhancedChangesList.php336
-rw-r--r--includes/changes/OldChangesList.php95
-rw-r--r--includes/changes/RCCacheEntry.php16
-rw-r--r--includes/changes/RCCacheEntryFactory.php275
-rw-r--r--includes/changes/RecentChange.php523
7 files changed, 1128 insertions, 607 deletions
diff --git a/includes/changes/ChangesFeed.php b/includes/changes/ChangesFeed.php
new file mode 100644
index 00000000..2d3b919d
--- /dev/null
+++ b/includes/changes/ChangesFeed.php
@@ -0,0 +1,240 @@
+<?php
+/**
+ * Feed for list of changes.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ * http://www.gnu.org/copyleft/gpl.html
+ *
+ * @file
+ */
+
+/**
+ * Feed to Special:RecentChanges and Special:RecentChangesLiked
+ *
+ * @ingroup Feed
+ */
+class ChangesFeed {
+ public $format, $type, $titleMsg, $descMsg;
+
+ /**
+ * Constructor
+ *
+ * @param string $format Feed's format (either 'rss' or 'atom')
+ * @param string $type Type of feed (for cache keys)
+ */
+ public function __construct( $format, $type ) {
+ $this->format = $format;
+ $this->type = $type;
+ }
+
+ /**
+ * Get a ChannelFeed subclass object to use
+ *
+ * @param string $title Feed's title
+ * @param string $description Feed's description
+ * @param string $url Url of origin page
+ * @return ChannelFeed|bool ChannelFeed subclass or false on failure
+ */
+ public function getFeedObject( $title, $description, $url ) {
+ global $wgSitename, $wgLanguageCode, $wgFeedClasses;
+
+ if ( !isset( $wgFeedClasses[$this->format] ) ) {
+ return false;
+ }
+
+ if ( !array_key_exists( $this->format, $wgFeedClasses ) ) {
+ // falling back to atom
+ $this->format = 'atom';
+ }
+
+ $feedTitle = "$wgSitename - {$title} [$wgLanguageCode]";
+ return new $wgFeedClasses[$this->format](
+ $feedTitle, htmlspecialchars( $description ), $url );
+ }
+
+ /**
+ * Generates feed's content
+ *
+ * @param ChannelFeed $feed ChannelFeed subclass object (generally the one returned
+ * by getFeedObject())
+ * @param ResultWrapper $rows ResultWrapper object with rows in recentchanges table
+ * @param int $lastmod Timestamp of the last item in the recentchanges table (only
+ * used for the cache key)
+ * @param FormOptions $opts As in SpecialRecentChanges::getDefaultOptions()
+ * @return null|bool True or null
+ */
+ public function execute( $feed, $rows, $lastmod, $opts ) {
+ global $wgLang, $wgRenderHashAppend;
+
+ if ( !FeedUtils::checkFeedOutput( $this->format ) ) {
+ return null;
+ }
+
+ $optionsHash = md5( serialize( $opts->getAllValues() ) ) . $wgRenderHashAppend;
+ $timekey = wfMemcKey( $this->type, $this->format, $wgLang->getCode(), $optionsHash, 'timestamp' );
+ $key = wfMemcKey( $this->type, $this->format, $wgLang->getCode(), $optionsHash );
+
+ FeedUtils::checkPurge( $timekey, $key );
+
+ /**
+ * Bumping around loading up diffs can be pretty slow, so where
+ * possible we want to cache the feed output so the next visitor
+ * gets it quick too.
+ */
+ $cachedFeed = $this->loadFromCache( $lastmod, $timekey, $key );
+ if ( is_string( $cachedFeed ) ) {
+ wfDebug( "RC: Outputting cached feed\n" );
+ $feed->httpHeaders();
+ echo $cachedFeed;
+ } else {
+ wfDebug( "RC: rendering new feed and caching it\n" );
+ ob_start();
+ self::generateFeed( $rows, $feed );
+ $cachedFeed = ob_get_contents();
+ ob_end_flush();
+ $this->saveToCache( $cachedFeed, $timekey, $key );
+ }
+ return true;
+ }
+
+ /**
+ * Save to feed result to $messageMemc
+ *
+ * @param string $feed Feed's content
+ * @param string $timekey Memcached key of the last modification
+ * @param string $key Memcached key of the content
+ */
+ public function saveToCache( $feed, $timekey, $key ) {
+ global $messageMemc;
+ $expire = 3600 * 24; # One day
+ $messageMemc->set( $key, $feed, $expire );
+ $messageMemc->set( $timekey, wfTimestamp( TS_MW ), $expire );
+ }
+
+ /**
+ * Try to load the feed result from $messageMemc
+ *
+ * @param int $lastmod Timestamp of the last item in the recentchanges table
+ * @param string $timekey Memcached key of the last modification
+ * @param string $key Memcached key of the content
+ * @return string|bool Feed's content on cache hit or false on cache miss
+ */
+ public function loadFromCache( $lastmod, $timekey, $key ) {
+ global $wgFeedCacheTimeout, $wgOut, $messageMemc;
+
+ $feedLastmod = $messageMemc->get( $timekey );
+
+ if ( ( $wgFeedCacheTimeout > 0 ) && $feedLastmod ) {
+ /**
+ * If the cached feed was rendered very recently, we may
+ * go ahead and use it even if there have been edits made
+ * since it was rendered. This keeps a swarm of requests
+ * from being too bad on a super-frequently edited wiki.
+ */
+
+ $feedAge = time() - wfTimestamp( TS_UNIX, $feedLastmod );
+ $feedLastmodUnix = wfTimestamp( TS_UNIX, $feedLastmod );
+ $lastmodUnix = wfTimestamp( TS_UNIX, $lastmod );
+
+ if ( $feedAge < $wgFeedCacheTimeout || $feedLastmodUnix > $lastmodUnix ) {
+ wfDebug( "RC: loading feed from cache ($key; $feedLastmod; $lastmod)...\n" );
+ if ( $feedLastmodUnix < $lastmodUnix ) {
+ $wgOut->setLastModified( $feedLastmod ); // bug 21916
+ }
+ return $messageMemc->get( $key );
+ } else {
+ wfDebug( "RC: cached feed timestamp check failed ($feedLastmod; $lastmod)\n" );
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Generate the feed items given a row from the database, printing the feed.
+ * @param object $rows DatabaseBase resource with recentchanges rows
+ * @param Feed $feed
+ */
+ public static function generateFeed( $rows, &$feed ) {
+ wfProfileIn( __METHOD__ );
+ $items = self::buildItems( $rows );
+ $feed->outHeader();
+ foreach ( $items as $item ) {
+ $feed->outItem( $item );
+ }
+ $feed->outFooter();
+ wfProfileOut( __METHOD__ );
+ }
+
+ /**
+ * Generate the feed items given a row from the database.
+ * @param object $rows DatabaseBase resource with recentchanges rows
+ * @return array
+ */
+ public static function buildItems( $rows ) {
+ wfProfileIn( __METHOD__ );
+ $items = array();
+
+ # Merge adjacent edits by one user
+ $sorted = array();
+ $n = 0;
+ foreach ( $rows as $obj ) {
+ if ( $n > 0 &&
+ $obj->rc_type == RC_EDIT &&
+ $obj->rc_namespace >= 0 &&
+ $obj->rc_cur_id == $sorted[$n - 1]->rc_cur_id &&
+ $obj->rc_user_text == $sorted[$n - 1]->rc_user_text ) {
+ $sorted[$n - 1]->rc_last_oldid = $obj->rc_last_oldid;
+ } else {
+ $sorted[$n] = $obj;
+ $n++;
+ }
+ }
+
+ foreach ( $sorted as $obj ) {
+ $title = Title::makeTitle( $obj->rc_namespace, $obj->rc_title );
+ $talkpage = MWNamespace::canTalk( $obj->rc_namespace )
+ ? $title->getTalkPage()->getFullURL()
+ : '';
+
+ // Skip items with deleted content (avoids partially complete/inconsistent output)
+ if ( $obj->rc_deleted ) {
+ continue;
+ }
+
+ if ( $obj->rc_this_oldid ) {
+ $url = $title->getFullURL( array(
+ 'diff' => $obj->rc_this_oldid,
+ 'oldid' => $obj->rc_last_oldid,
+ ) );
+ } else {
+ // log entry or something like that.
+ $url = $title->getFullURL();
+ }
+
+ $items[] = new FeedItem(
+ $title->getPrefixedText(),
+ FeedUtils::formatDiff( $obj ),
+ $url,
+ $obj->rc_timestamp,
+ ( $obj->rc_deleted & Revision::DELETED_USER )
+ ? wfMessage( 'rev-deleted-user' )->escaped() : $obj->rc_user_text,
+ $talkpage
+ );
+ }
+
+ wfProfileOut( __METHOD__ );
+ return $items;
+ }
+}
diff --git a/includes/changes/ChangesList.php b/includes/changes/ChangesList.php
index bf800c46..03d1289f 100644
--- a/includes/changes/ChangesList.php
+++ b/includes/changes/ChangesList.php
@@ -23,20 +23,26 @@
*/
class ChangesList extends ContextSource {
-
/**
* @var Skin
*/
public $skin;
protected $watchlist = false;
-
+ protected $lastdate;
protected $message;
+ protected $rc_cache;
+ protected $rcCacheIndex;
+ protected $rclistOpen;
+ protected $rcMoveIndex;
+
+ /** @var MapCacheLRU */
+ protected $watchingCache;
/**
* Changeslist constructor
*
- * @param $obj Skin or IContextSource
+ * @param Skin|IContextSource $obj
*/
public function __construct( $obj ) {
if ( $obj instanceof IContextSource ) {
@@ -47,27 +53,15 @@ class ChangesList extends ContextSource {
$this->skin = $obj;
}
$this->preCacheMessages();
- }
-
- /**
- * Fetch an appropriate changes list class for the main context
- * This first argument used to be an User object.
- *
- * @deprecated in 1.18; use newFromContext() instead
- * @param string|User $unused Unused
- * @return ChangesList|EnhancedChangesList|OldChangesList derivative
- */
- public static function newFromUser( $unused ) {
- wfDeprecated( __METHOD__, '1.18' );
- return self::newFromContext( RequestContext::getMain() );
+ $this->watchingCache = new MapCacheLRU( 50 );
}
/**
* Fetch an appropriate changes list class for the specified context
* Some users might want to use an enhanced list format, for instance
*
- * @param $context IContextSource to use
- * @return ChangesList|EnhancedChangesList|OldChangesList derivative
+ * @param IContextSource $context
+ * @return ChangesList
*/
public static function newFromContext( IContextSource $context ) {
$user = $context->getUser();
@@ -75,6 +69,7 @@ class ChangesList extends ContextSource {
$list = null;
if ( wfRunHooks( 'FetchChangesList', array( $user, &$sk, &$list ) ) ) {
$new = $context->getRequest()->getBool( 'enhanced', $user->getOption( 'usenewrc' ) );
+
return $new ? new EnhancedChangesList( $context ) : new OldChangesList( $context );
} else {
return $list;
@@ -83,13 +78,21 @@ class ChangesList extends ContextSource {
/**
* Sets the list to use a "<li class='watchlist-(namespace)-(page)'>" tag
- * @param $value Boolean
+ * @param bool $value
*/
public function setWatchlistDivs( $value = true ) {
$this->watchlist = $value;
}
/**
+ * @return bool True when setWatchlistDivs has been called
+ * @since 1.23
+ */
+ public function isWatchlist() {
+ return (bool)$this->watchlist;
+ }
+
+ /**
* As we use the same small set of messages in various methods and that
* they are called often, we call them once and save them in $this->message
*/
@@ -107,17 +110,17 @@ class ChangesList extends ContextSource {
/**
* Returns the appropriate flags for new page, minor change and patrolling
* @param array $flags Associative array of 'flag' => Bool
- * @param string $nothing to use for empty space
- * @return String
+ * @param string $nothing To use for empty space
+ * @return string
*/
public function recentChangesFlags( $flags, $nothing = '&#160;' ) {
- global $wgRecentChangesFlags;
$f = '';
- foreach ( array_keys( $wgRecentChangesFlags ) as $flag ) {
+ foreach ( array_keys( $this->getConfig()->get( 'RecentChangesFlags' ) ) as $flag ) {
$f .= isset( $flags[$flag] ) && $flags[$flag]
? self::flag( $flag )
: $nothing;
}
+
return $f;
}
@@ -128,7 +131,7 @@ class ChangesList extends ContextSource {
* "!" respectively, plus it will have an appropriate title and class.
*
* @param string $flag One key of $wgRecentChangesFlags
- * @return String: Raw HTML
+ * @return string Raw HTML
*/
public static function flag( $flag ) {
static $flagInfos = null;
@@ -153,14 +156,14 @@ class ChangesList extends ContextSource {
$flag = $map[$flag];
}
- return "<abbr class='" . $flagInfos[$flag]['class'] . "' title='" . $flagInfos[$flag]['title'] . "'>" .
- $flagInfos[$flag]['letter'] .
+ return "<abbr class='" . $flagInfos[$flag]['class'] . "' title='" .
+ $flagInfos[$flag]['title'] . "'>" . $flagInfos[$flag]['letter'] .
'</abbr>';
}
/**
* Returns text for the start of the tabular part of RC
- * @return String
+ * @return string
*/
public function beginRecentChangesList() {
$this->rc_cache = array();
@@ -169,19 +172,25 @@ class ChangesList extends ContextSource {
$this->lastdate = '';
$this->rclistOpen = false;
$this->getOutput()->addModuleStyles( 'mediawiki.special.changeslist' );
- return '';
+
+ return '<div class="mw-changeslist">';
+ }
+
+ /**
+ * @param ResultWrapper|array $rows
+ */
+ public function initChangesListRows( $rows ) {
+ wfRunHooks( 'ChangesListInitRows', array( $this, $rows ) );
}
/**
* Show formatted char difference
- * @param $old Integer: bytes
- * @param $new Integer: bytes
- * @param $context IContextSource context to use
- * @return String
+ * @param int $old Number of bytes
+ * @param int $new Number of bytes
+ * @param IContextSource $context
+ * @return string
*/
public static function showCharacterDifference( $old, $new, IContextSource $context = null ) {
- global $wgRCChangedSizeThreshold, $wgMiserMode;
-
if ( !$context ) {
$context = RequestContext::getMain();
}
@@ -191,10 +200,11 @@ class ChangesList extends ContextSource {
$szdiff = $new - $old;
$lang = $context->getLanguage();
+ $config = $context->getConfig();
$code = $lang->getCode();
static $fastCharDiff = array();
if ( !isset( $fastCharDiff[$code] ) ) {
- $fastCharDiff[$code] = $wgMiserMode || $context->msg( 'rc-change-size' )->plain() === '$1';
+ $fastCharDiff[$code] = $config->get( 'MiserMode' ) || $context->msg( 'rc-change-size' )->plain() === '$1';
}
$formattedSize = $lang->formatNum( $szdiff );
@@ -203,7 +213,7 @@ class ChangesList extends ContextSource {
$formattedSize = $context->msg( 'rc-change-size', $formattedSize )->text();
}
- if ( abs( $szdiff ) > abs( $wgRCChangedSizeThreshold ) ) {
+ if ( abs( $szdiff ) > abs( $config->get( 'RCChangedSizeThreshold' ) ) ) {
$tag = 'strong';
} else {
$tag = 'span';
@@ -211,12 +221,10 @@ class ChangesList extends ContextSource {
if ( $szdiff === 0 ) {
$formattedSizeClass = 'mw-plusminus-null';
- }
- if ( $szdiff > 0 ) {
+ } elseif ( $szdiff > 0 ) {
$formattedSize = '+' . $formattedSize;
$formattedSizeClass = 'mw-plusminus-pos';
- }
- if ( $szdiff < 0 ) {
+ } else {
$formattedSizeClass = 'mw-plusminus-neg';
}
@@ -230,8 +238,8 @@ class ChangesList extends ContextSource {
/**
* Format the character difference of one or several changes.
*
- * @param $old RecentChange
- * @param $new RecentChange last change to use, if not provided, $old will be used
+ * @param RecentChange $old
+ * @param RecentChange $new Last change to use, if not provided, $old will be used
* @return string HTML fragment
*/
public function formatCharacterDifference( RecentChange $old, RecentChange $new = null ) {
@@ -252,19 +260,18 @@ class ChangesList extends ContextSource {
/**
* Returns text for the end of RC
- * @return String
+ * @return string
*/
public function endRecentChangesList() {
- if ( $this->rclistOpen ) {
- return "</ul>\n";
- } else {
- return '';
- }
+ $out = $this->rclistOpen ? "</ul>\n" : '';
+ $out .= '</div>';
+
+ return $out;
}
/**
* @param string $s HTML to update
- * @param $rc_timestamp mixed
+ * @param mixed $rc_timestamp
*/
public function insertDateHeader( &$s, $rc_timestamp ) {
# Make date header if necessary
@@ -281,8 +288,8 @@ class ChangesList extends ContextSource {
/**
* @param string $s HTML to update
- * @param $title Title
- * @param $logtype string
+ * @param Title $title
+ * @param string $logtype
*/
public function insertLog( &$s, $title, $logtype ) {
$page = new LogPage( $logtype );
@@ -292,8 +299,8 @@ class ChangesList extends ContextSource {
/**
* @param string $s HTML to update
- * @param $rc RecentChange
- * @param $unpatrolled
+ * @param RecentChange $rc
+ * @param bool $unpatrolled
*/
public function insertDiffHist( &$s, &$rc, $unpatrolled ) {
# Diff link
@@ -326,17 +333,22 @@ class ChangesList extends ContextSource {
'action' => 'history'
)
);
- $s .= $this->msg( 'parentheses' )->rawParams( $diffhist )->escaped() . ' <span class="mw-changeslist-separator">. .</span> ';
+ // @todo FIXME: Hard coded ". .". Is there a message for this? Should there be?
+ $s .= $this->msg( 'parentheses' )->rawParams( $diffhist )->escaped() .
+ ' <span class="mw-changeslist-separator">. .</span> ';
}
/**
* @param string $s HTML to update
- * @param $rc RecentChange
- * @param $unpatrolled
- * @param $watched
+ * @param RecentChange $rc
+ * @param bool $unpatrolled
+ * @param bool $watched
*/
public function insertArticleLink( &$s, &$rc, $unpatrolled, $watched ) {
$params = array();
+ if ( $rc->getTitle()->isRedirect() ) {
+ $params = array( 'redirect' => 'no' );
+ }
$articlelink = Linker::linkKnown(
$rc->getTitle(),
@@ -362,19 +374,23 @@ class ChangesList extends ContextSource {
* Get the timestamp from $rc formatted with current user's settings
* and a separator
*
- * @param $rc RecentChange
+ * @param RecentChange $rc
* @return string HTML fragment
*/
public function getTimestamp( $rc ) {
+ // @todo FIXME: Hard coded ". .". Is there a message for this? Should there be?
return $this->message['semicolon-separator'] . '<span class="mw-changeslist-date">' .
- $this->getLanguage()->userTime( $rc->mAttribs['rc_timestamp'], $this->getUser() ) . '</span> <span class="mw-changeslist-separator">. .</span> ';
+ $this->getLanguage()->userTime(
+ $rc->mAttribs['rc_timestamp'],
+ $this->getUser()
+ ) . '</span> <span class="mw-changeslist-separator">. .</span> ';
}
/**
* Insert time timestamp string from $rc into $s
*
* @param string $s HTML to update
- * @param $rc RecentChange
+ * @param RecentChange $rc
*/
public function insertTimestamp( &$s, $rc ) {
$s .= $this->getTimestamp( $rc );
@@ -383,12 +399,13 @@ class ChangesList extends ContextSource {
/**
* Insert links to user page, user talk page and eventually a blocking link
*
- * @param &$s String HTML to update
- * @param &$rc RecentChange
+ * @param string &$s HTML to update
+ * @param RecentChange &$rc
*/
public function insertUserRelatedLinks( &$s, &$rc ) {
if ( $this->isDeleted( $rc, Revision::DELETED_USER ) ) {
- $s .= ' <span class="history-deleted">' . $this->msg( 'rev-deleted-user' )->escaped() . '</span>';
+ $s .= ' <span class="history-deleted">' .
+ $this->msg( 'rev-deleted-user' )->escaped() . '</span>';
} else {
$s .= $this->getLanguage()->getDirMark() . Linker::userLink( $rc->mAttribs['rc_user'],
$rc->mAttribs['rc_user_text'] );
@@ -399,7 +416,7 @@ class ChangesList extends ContextSource {
/**
* Insert a formatted action
*
- * @param $rc RecentChange
+ * @param RecentChange $rc
* @return string
*/
public function insertLogEntry( $rc ) {
@@ -407,30 +424,29 @@ class ChangesList extends ContextSource {
$formatter->setContext( $this->getContext() );
$formatter->setShowUserToolLinks( true );
$mark = $this->getLanguage()->getDirMark();
+
return $formatter->getActionText() . " $mark" . $formatter->getComment();
}
/**
* Insert a formatted comment
- * @param $rc RecentChange
+ * @param RecentChange $rc
* @return string
*/
public function insertComment( $rc ) {
- if ( $rc->mAttribs['rc_type'] != RC_MOVE && $rc->mAttribs['rc_type'] != RC_MOVE_OVER_REDIRECT ) {
- if ( $this->isDeleted( $rc, Revision::DELETED_COMMENT ) ) {
- return ' <span class="history-deleted">' . $this->msg( 'rev-deleted-comment' )->escaped() . '</span>';
- } else {
- return Linker::commentBlock( $rc->mAttribs['rc_comment'], $rc->getTitle() );
- }
+ if ( $this->isDeleted( $rc, Revision::DELETED_COMMENT ) ) {
+ return ' <span class="history-deleted">' .
+ $this->msg( 'rev-deleted-comment' )->escaped() . '</span>';
+ } else {
+ return Linker::commentBlock( $rc->mAttribs['rc_comment'], $rc->getTitle() );
}
- return '';
}
/**
* Check whether to enable recent changes patrol features
*
* @deprecated since 1.22
- * @return Boolean
+ * @return bool
*/
public static function usePatrol() {
global $wgUser;
@@ -442,15 +458,18 @@ class ChangesList extends ContextSource {
/**
* Returns the string which indicates the number of watching users
+ * @param int $count Number of user watching a page
* @return string
*/
protected function numberofWatchingusers( $count ) {
- static $cache = array();
+ $cache = $this->watchingCache;
if ( $count > 0 ) {
- if ( !isset( $cache[$count] ) ) {
- $cache[$count] = $this->msg( 'number_of_watching_users_RCview' )->numParams( $count )->escaped();
+ if ( !$cache->has( $count ) ) {
+ $cache->set( $count, $this->msg( 'number_of_watching_users_RCview' )
+ ->numParams( $count )->escaped() );
}
- return $cache[$count];
+
+ return $cache->get( $count );
} else {
return '';
}
@@ -458,9 +477,9 @@ class ChangesList extends ContextSource {
/**
* Determine if said field of a revision is hidden
- * @param $rc RCCacheEntry
- * @param $field Integer: one of DELETED_* bitfield constants
- * @return Boolean
+ * @param RCCacheEntry|RecentChange $rc
+ * @param int $field One of DELETED_* bitfield constants
+ * @return bool
*/
public static function isDeleted( $rc, $field ) {
return ( $rc->mAttribs['rc_deleted'] & $field ) == $field;
@@ -469,10 +488,10 @@ class ChangesList extends ContextSource {
/**
* Determine if the current user is allowed to view a particular
* field of this revision, if it's marked as deleted.
- * @param $rc RCCacheEntry
- * @param $field Integer
- * @param $user User object to check, or null to use $wgUser
- * @return Boolean
+ * @param RCCacheEntry|RecentChange $rc
+ * @param int $field
+ * @param User $user User object to check, or null to use $wgUser
+ * @return bool
*/
public static function userCan( $rc, $field, User $user = null ) {
if ( $rc->mAttribs['rc_type'] == RC_LOG ) {
@@ -483,8 +502,8 @@ class ChangesList extends ContextSource {
}
/**
- * @param $link string
- * @param $watched bool
+ * @param string $link
+ * @param bool $watched
* @return string
*/
protected function maybeWatchedLink( $link, $watched = false ) {
@@ -497,16 +516,20 @@ class ChangesList extends ContextSource {
/** Inserts a rollback link
*
- * @param $s string
- * @param $rc RecentChange
+ * @param string $s
+ * @param RecentChange $rc
*/
public function insertRollback( &$s, &$rc ) {
- if ( $rc->mAttribs['rc_type'] == RC_EDIT && $rc->mAttribs['rc_this_oldid'] && $rc->mAttribs['rc_cur_id'] ) {
+ if ( $rc->mAttribs['rc_type'] == RC_EDIT
+ && $rc->mAttribs['rc_this_oldid']
+ && $rc->mAttribs['rc_cur_id']
+ ) {
$page = $rc->getTitle();
/** Check for rollback and edit permissions, disallow special pages, and only
- * show a link on the top-most revision */
- if ( $this->getUser()->isAllowed( 'rollback' ) && $rc->mAttribs['page_latest'] == $rc->mAttribs['rc_this_oldid'] )
- {
+ * show a link on the top-most revision */
+ if ( $this->getUser()->isAllowed( 'rollback' )
+ && $rc->mAttribs['page_latest'] == $rc->mAttribs['rc_this_oldid']
+ ) {
$rev = new Revision( array(
'title' => $page,
'id' => $rc->mAttribs['rc_this_oldid'],
@@ -520,16 +543,19 @@ class ChangesList extends ContextSource {
}
/**
- * @param $s string
- * @param $rc RecentChange
- * @param $classes
+ * @param string $s
+ * @param RecentChange $rc
+ * @param array $classes
*/
public function insertTags( &$s, &$rc, &$classes ) {
if ( empty( $rc->mAttribs['ts_tags'] ) ) {
return;
}
- list( $tagSummary, $newClasses ) = ChangeTags::formatSummaryRow( $rc->mAttribs['ts_tags'], 'changeslist' );
+ list( $tagSummary, $newClasses ) = ChangeTags::formatSummaryRow(
+ $rc->mAttribs['ts_tags'],
+ 'changeslist'
+ );
$classes = array_merge( $classes, $newClasses );
$s .= ' ' . $tagSummary;
}
@@ -539,14 +565,32 @@ class ChangesList extends ContextSource {
}
protected function showAsUnpatrolled( RecentChange $rc ) {
- $unpatrolled = false;
- if ( !$rc->mAttribs['rc_patrolled'] ) {
- if ( $this->getUser()->useRCPatrol() ) {
- $unpatrolled = true;
- } elseif ( $this->getUser()->useNPPatrol() && $rc->mAttribs['rc_type'] == RC_NEW ) {
- $unpatrolled = true;
+ return self::isUnpatrolled( $rc, $this->getUser() );
+ }
+
+ /**
+ * @param object|RecentChange $rc Database row from recentchanges or a RecentChange object
+ * @param User $user
+ * @return bool
+ */
+ public static function isUnpatrolled( $rc, User $user ) {
+ if ( $rc instanceof RecentChange ) {
+ $isPatrolled = $rc->mAttribs['rc_patrolled'];
+ $rcType = $rc->mAttribs['rc_type'];
+ } else {
+ $isPatrolled = $rc->rc_patrolled;
+ $rcType = $rc->rc_type;
+ }
+
+ if ( !$isPatrolled ) {
+ if ( $user->useRCPatrol() ) {
+ return true;
+ }
+ if ( $user->useNPPatrol() && $rcType == RC_NEW ) {
+ return true;
}
}
- return $unpatrolled;
+
+ return false;
}
}
diff --git a/includes/changes/EnhancedChangesList.php b/includes/changes/EnhancedChangesList.php
index 4c8aa451..4ab77297 100644
--- a/includes/changes/EnhancedChangesList.php
+++ b/includes/changes/EnhancedChangesList.php
@@ -22,11 +22,44 @@
class EnhancedChangesList extends ChangesList {
+ /**
+ * @var RCCacheEntryFactory
+ */
+ protected $cacheEntryFactory;
+
+ /**
+ * @var array Array of array of RCCacheEntry
+ */
protected $rc_cache;
/**
+ * @param IContextSource|Skin $obj
+ */
+ public function __construct( $obj ) {
+ if ( $obj instanceof Skin ) {
+ // @todo: deprecate constructing with Skin
+ $context = $obj->getContext();
+ } else {
+ if ( !$obj instanceof IContextSource ) {
+ throw new MWException( 'EnhancedChangesList must be constructed with a '
+ . 'context source or skin.' );
+ }
+
+ $context = $obj;
+ }
+
+ parent::__construct( $context );
+
+ // message is set by the parent ChangesList class
+ $this->cacheEntryFactory = new RCCacheEntryFactory(
+ $context,
+ $this->message
+ );
+ }
+
+ /**
* Add the JavaScript file for enhanced changeslist
- * @return String
+ * @return string
*/
public function beginRecentChangesList() {
$this->rc_cache = array();
@@ -42,27 +75,29 @@ class EnhancedChangesList extends ChangesList {
'jquery.makeCollapsible',
'mediawiki.icon',
) );
- return '';
+
+ return '<div class="mw-changeslist">';
}
+
/**
* Format a line for enhanced recentchange (aka with javascript and block of lines).
*
- * @param $baseRC RecentChange
- * @param $watched bool
+ * @param RecentChange $baseRC
+ * @param bool $watched
*
* @return string
*/
public function recentChangesLine( &$baseRC, $watched = false ) {
wfProfileIn( __METHOD__ );
- # Create a specialised object
- $rc = RCCacheEntry::newFromParent( $baseRC );
+ $date = $this->getLanguage()->userDate(
+ $baseRC->mAttribs['rc_timestamp'],
+ $this->getUser()
+ );
- $curIdEq = array( 'curid' => $rc->mAttribs['rc_cur_id'] );
+ $ret = '';
# If it's a new day, add the headline and flush the cache
- $date = $this->getLanguage()->userDate( $rc->mAttribs['rc_timestamp'], $this->getUser() );
- $ret = '';
if ( $date != $this->lastdate ) {
# Process current cache
$ret = $this->recentChangesBlock();
@@ -71,128 +106,60 @@ class EnhancedChangesList extends ChangesList {
$this->lastdate = $date;
}
- # Should patrol-related stuff be shown?
- $rc->unpatrolled = $this->showAsUnpatrolled( $rc );
-
- $showdifflinks = true;
- # Make article link
- $type = $rc->mAttribs['rc_type'];
- $logType = $rc->mAttribs['rc_log_type'];
- // Page moves, very old style, not supported anymore
- if ( $type == RC_MOVE || $type == RC_MOVE_OVER_REDIRECT ) {
- // New unpatrolled pages
- } elseif ( $rc->unpatrolled && $type == RC_NEW ) {
- $clink = Linker::linkKnown( $rc->getTitle() );
- // Log entries
- } elseif ( $type == RC_LOG ) {
- if ( $logType ) {
- $logtitle = SpecialPage::getTitleFor( 'Log', $logType );
- $logpage = new LogPage( $logType );
- $logname = $logpage->getName()->escaped();
- $clink = $this->msg( 'parentheses' )->rawParams( Linker::linkKnown( $logtitle, $logname ) )->escaped();
- } else {
- $clink = Linker::link( $rc->getTitle() );
- }
- $watched = false;
- // Log entries (old format) and special pages
- } elseif ( $rc->mAttribs['rc_namespace'] == NS_SPECIAL ) {
- wfDebug( "Unexpected special page in recentchanges\n" );
- $clink = '';
- // Edits
- } else {
- $clink = Linker::linkKnown( $rc->getTitle() );
- }
+ $cacheEntry = $this->cacheEntryFactory->newFromRecentChange( $baseRC, $watched );
+ $this->addCacheEntry( $cacheEntry );
- # Don't show unusable diff links
- if ( !ChangesList::userCan( $rc, Revision::DELETED_TEXT, $this->getUser() ) ) {
- $showdifflinks = false;
- }
+ wfProfileOut( __METHOD__ );
- $time = $this->getLanguage()->userTime( $rc->mAttribs['rc_timestamp'], $this->getUser() );
- $rc->watched = $watched;
- $rc->link = $clink;
- $rc->timestamp = $time;
- $rc->numberofWatchingusers = $baseRC->numberofWatchingusers;
-
- # Make "cur" and "diff" links. Do not use link(), it is too slow if
- # called too many times (50% of CPU time on RecentChanges!).
- $thisOldid = $rc->mAttribs['rc_this_oldid'];
- $lastOldid = $rc->mAttribs['rc_last_oldid'];
-
- $querycur = $curIdEq + array( 'diff' => '0', 'oldid' => $thisOldid );
- $querydiff = $curIdEq + array( 'diff' => $thisOldid, 'oldid' => $lastOldid );
-
- if ( !$showdifflinks ) {
- $curLink = $this->message['cur'];
- $diffLink = $this->message['diff'];
- } elseif ( in_array( $type, array( RC_NEW, RC_LOG, RC_MOVE, RC_MOVE_OVER_REDIRECT ) ) ) {
- if ( $type != RC_NEW ) {
- $curLink = $this->message['cur'];
- } else {
- $curUrl = htmlspecialchars( $rc->getTitle()->getLinkURL( $querycur ) );
- $curLink = "<a href=\"$curUrl\" tabindex=\"{$baseRC->counter}\">{$this->message['cur']}</a>";
- }
- $diffLink = $this->message['diff'];
- } else {
- $diffUrl = htmlspecialchars( $rc->getTitle()->getLinkURL( $querydiff ) );
- $curUrl = htmlspecialchars( $rc->getTitle()->getLinkURL( $querycur ) );
- $diffLink = "<a href=\"$diffUrl\" tabindex=\"{$baseRC->counter}\">{$this->message['diff']}</a>";
- $curLink = "<a href=\"$curUrl\" tabindex=\"{$baseRC->counter}\">{$this->message['cur']}</a>";
- }
+ return $ret;
+ }
- # Make "last" link
- if ( !$showdifflinks || !$lastOldid ) {
- $lastLink = $this->message['last'];
- } elseif ( in_array( $type, array( RC_LOG, RC_MOVE, RC_MOVE_OVER_REDIRECT ) ) ) {
- $lastLink = $this->message['last'];
- } else {
- $lastLink = Linker::linkKnown( $rc->getTitle(), $this->message['last'],
- array(), $curIdEq + array( 'diff' => $thisOldid, 'oldid' => $lastOldid ) );
- }
+ /**
+ * Put accumulated information into the cache, for later display.
+ * Page moves go on their own line.
+ *
+ * @param RCCacheEntry $cacheEntry
+ */
+ protected function addCacheEntry( RCCacheEntry $cacheEntry ) {
+ $cacheGroupingKey = $this->makeCacheGroupingKey( $cacheEntry );
- # Make user links
- if ( $this->isDeleted( $rc, Revision::DELETED_USER ) ) {
- $rc->userlink = ' <span class="history-deleted">' . $this->msg( 'rev-deleted-user' )->escaped() . '</span>';
- } else {
- $rc->userlink = Linker::userLink( $rc->mAttribs['rc_user'], $rc->mAttribs['rc_user_text'] );
- $rc->usertalklink = Linker::userToolLinks( $rc->mAttribs['rc_user'], $rc->mAttribs['rc_user_text'] );
+ if ( !isset( $this->rc_cache[$cacheGroupingKey] ) ) {
+ $this->rc_cache[$cacheGroupingKey] = array();
}
- $rc->lastlink = $lastLink;
- $rc->curlink = $curLink;
- $rc->difflink = $diffLink;
-
- # Put accumulated information into the cache, for later display
- # Page moves go on their own line
- $title = $rc->getTitle();
- $secureName = $title->getPrefixedDBkey();
- if ( $type == RC_MOVE || $type == RC_MOVE_OVER_REDIRECT ) {
- # Use an @ character to prevent collision with page names
- $this->rc_cache['@@' . ( $this->rcMoveIndex++ )] = array( $rc );
- } else {
- # Logs are grouped by type
- if ( $type == RC_LOG ) {
- $secureName = SpecialPage::getTitleFor( 'Log', $logType )->getPrefixedDBkey();
- }
- if ( !isset( $this->rc_cache[$secureName] ) ) {
- $this->rc_cache[$secureName] = array();
- }
+ array_push( $this->rc_cache[$cacheGroupingKey], $cacheEntry );
+ }
- array_push( $this->rc_cache[$secureName], $rc );
- }
+ /**
+ * @todo use rc_source to group, if set; fallback to rc_type
+ *
+ * @param RCCacheEntry $cacheEntry
+ *
+ * @return string
+ */
+ protected function makeCacheGroupingKey( RCCacheEntry $cacheEntry ) {
+ $title = $cacheEntry->getTitle();
+ $cacheGroupingKey = $title->getPrefixedDBkey();
- wfProfileOut( __METHOD__ );
+ $type = $cacheEntry->mAttribs['rc_type'];
- return $ret;
+ if ( $type == RC_LOG ) {
+ // Group by log type
+ $cacheGroupingKey = SpecialPage::getTitleFor(
+ 'Log',
+ $cacheEntry->mAttribs['rc_log_type']
+ )->getPrefixedDBkey();
+ }
+
+ return $cacheGroupingKey;
}
/**
* Enhanced RC group
+ * @param RCCacheEntry[] $block
* @return string
*/
protected function recentChangesBlockGroup( $block ) {
- global $wgRCShowChangedSize;
-
wfProfileIn( __METHOD__ );
# Add the namespace and title of the block as part of the class
@@ -203,7 +170,7 @@ class EnhancedChangesList extends ChangesList {
. $block[0]->mAttribs['rc_log_type'] );
} else {
$classes[] = Sanitizer::escapeClass( 'mw-changeslist-ns'
- . $block[0]->mAttribs['rc_namespace'] . '-' . $block[0]->mAttribs['rc_title'] );
+ . $block[0]->mAttribs['rc_namespace'] . '-' . $block[0]->mAttribs['rc_title'] );
}
$classes[] = $block[0]->watched && $block[0]->mAttribs['rc_timestamp'] >= $block[0]->watched
? 'mw-changeslist-line-watched' : 'mw-changeslist-line-not-watched';
@@ -221,6 +188,8 @@ class EnhancedChangesList extends ChangesList {
# Some catalyst variables...
$namehidden = true;
$allLogs = true;
+ $oldid = '';
+ $RCShowChangedSize = $this->getConfig()->get( 'RCShowChangedSize' );
foreach ( $block as $rcObj ) {
$oldid = $rcObj->mAttribs['rc_last_oldid'];
if ( $rcObj->mAttribs['rc_type'] == RC_NEW ) {
@@ -268,7 +237,9 @@ class EnhancedChangesList extends ChangesList {
$text = $userlink;
$text .= $this->getLanguage()->getDirMark();
if ( $count > 1 ) {
- $text .= ' ' . $this->msg( 'parentheses' )->rawParams( $this->getLanguage()->formatNum( $count ) . '×' )->escaped();
+ // @todo FIXME: Hardcoded '×'. Should be a message.
+ $formattedCount = $this->getLanguage()->formatNum( $count ) . '×';
+ $text .= ' ' . $this->msg( 'parentheses' )->rawParams( $formattedCount )->escaped();
}
array_push( $users, $text );
}
@@ -278,7 +249,8 @@ class EnhancedChangesList extends ChangesList {
implode( $this->message['semicolon-separator'], $users )
)->escaped() . '</span>';
- $tl = '<span class="mw-collapsible-toggle mw-collapsible-arrow mw-enhancedchanges-arrow mw-enhancedchanges-arrow-space"></span>';
+ $tl = '<span class="mw-collapsible-toggle mw-collapsible-arrow ' .
+ 'mw-enhancedchanges-arrow mw-enhancedchanges-arrow-space"></span>';
$r .= "<td>$tl</td>";
# Main line
@@ -294,7 +266,8 @@ class EnhancedChangesList extends ChangesList {
# Article link
if ( $namehidden ) {
- $r .= ' <span class="history-deleted">' . $this->msg( 'rev-deleted-event' )->escaped() . '</span>';
+ $r .= ' <span class="history-deleted">' .
+ $this->msg( 'rev-deleted-event' )->escaped() . '</span>';
} elseif ( $allLogs ) {
$r .= $this->maybeWatchedLink( $block[0]->link, $block[0]->watched );
} else {
@@ -316,6 +289,7 @@ class EnhancedChangesList extends ChangesList {
$sinceLast = 0;
$unvisitedOldid = null;
+ /** @var $rcObj RCCacheEntry */
foreach ( $block as $rcObj ) {
// Same logic as below inside main foreach
if ( $rcObj->watched && $rcObj->mAttribs['rc_timestamp'] >= $rcObj->watched ) {
@@ -331,6 +305,8 @@ class EnhancedChangesList extends ChangesList {
# Total change link
$r .= ' ';
$logtext = '';
+ /** @var $block0 RecentChange */
+ $block0 = $block[0];
if ( !$allLogs ) {
if ( !ChangesList::userCan( $rcObj, Revision::DELETED_TEXT, $this->getUser() ) ) {
$logtext .= $nchanges[$n];
@@ -338,7 +314,7 @@ class EnhancedChangesList extends ChangesList {
$logtext .= $nchanges[$n];
} else {
$logtext .= Linker::link(
- $block[0]->getTitle(),
+ $block0->getTitle(),
$nchanges[$n],
array(),
$queryParams + array(
@@ -349,7 +325,7 @@ class EnhancedChangesList extends ChangesList {
);
if ( $sinceLast > 0 && $sinceLast < $n ) {
$logtext .= $this->message['pipe-separator'] . Linker::link(
- $block[0]->getTitle(),
+ $block0->getTitle(),
$sinceLastVisitMsg[$sinceLast],
array(),
$queryParams + array(
@@ -365,7 +341,7 @@ class EnhancedChangesList extends ChangesList {
# History
if ( $allLogs ) {
// don't show history link for logs
- } elseif ( $namehidden || !$block[0]->getTitle()->exists() ) {
+ } elseif ( $namehidden || !$block0->getTitle()->exists() ) {
$logtext .= $this->message['pipe-separator'] . $this->message['enhancedrc-history'];
} else {
$params = $queryParams;
@@ -373,7 +349,7 @@ class EnhancedChangesList extends ChangesList {
$logtext .= $this->message['pipe-separator'] .
Linker::linkKnown(
- $block[0]->getTitle(),
+ $block0->getTitle(),
$this->message['enhancedrc-history'],
array(),
$params
@@ -387,7 +363,7 @@ class EnhancedChangesList extends ChangesList {
$r .= ' <span class="mw-changeslist-separator">. .</span> ';
# Character difference (does not apply if only log items)
- if ( $wgRCShowChangedSize && !$allLogs ) {
+ if ( $RCShowChangedSize && !$allLogs ) {
$last = 0;
$first = count( $block ) - 1;
# Some events (like logs) have an "empty" size, so we need to skip those...
@@ -408,7 +384,8 @@ class EnhancedChangesList extends ChangesList {
}
$r .= $users;
- $r .= $this->numberofWatchingusers( $block[0]->numberofWatchingusers );
+ $r .= $this->numberofWatchingusers( $block0->numberofWatchingusers );
+ $r .= '</td></tr>';
# Sub-entries
foreach ( $block as $rcObj ) {
@@ -443,11 +420,11 @@ class EnhancedChangesList extends ChangesList {
} else {
$link = Linker::linkKnown(
- $rcObj->getTitle(),
- $rcObj->timestamp,
- array(),
- $params
- );
+ $rcObj->getTitle(),
+ $rcObj->timestamp,
+ array(),
+ $params
+ );
if ( $this->isDeleted( $rcObj, Revision::DELETED_TEXT ) ) {
$link = '<span class="history-deleted">' . $link . '</span> ';
}
@@ -455,12 +432,16 @@ class EnhancedChangesList extends ChangesList {
$r .= $link . '</span>';
if ( !$type == RC_LOG || $type == RC_NEW ) {
- $r .= ' ' . $this->msg( 'parentheses' )->rawParams( $rcObj->curlink . $this->message['pipe-separator'] . $rcObj->lastlink )->escaped();
+ $r .= ' ' . $this->msg( 'parentheses' )->rawParams(
+ $rcObj->curlink .
+ $this->message['pipe-separator'] .
+ $rcObj->lastlink
+ )->escaped();
}
$r .= ' <span class="mw-changeslist-separator">. .</span> ';
# Character diff
- if ( $wgRCShowChangedSize ) {
+ if ( $RCShowChangedSize ) {
$cd = $this->formatCharacterDifference( $rcObj );
if ( $cd !== '' ) {
$r .= $cd . ' <span class="mw-changeslist-separator">. .</span> ';
@@ -493,56 +474,12 @@ class EnhancedChangesList extends ChangesList {
}
/**
- * Generate HTML for an arrow or placeholder graphic
- * @param string $dir one of '', 'd', 'l', 'r'
- * @param string $alt text
- * @param string $title text
- * @return String: HTML "<img>" tag
- */
- protected function arrow( $dir, $alt = '', $title = '' ) {
- global $wgStylePath;
- $encUrl = htmlspecialchars( $wgStylePath . '/common/images/Arr_' . $dir . '.png' );
- $encAlt = htmlspecialchars( $alt );
- $encTitle = htmlspecialchars( $title );
- return "<img src=\"$encUrl\" width=\"12\" height=\"12\" alt=\"$encAlt\" title=\"$encTitle\" />";
- }
-
- /**
- * Generate HTML for a right- or left-facing arrow,
- * depending on language direction.
- * @return String: HTML "<img>" tag
- */
- protected function sideArrow() {
- $dir = $this->getLanguage()->isRTL() ? 'l' : 'r';
- return $this->arrow( $dir, '+', $this->msg( 'rc-enhanced-expand' )->text() );
- }
-
- /**
- * Generate HTML for a down-facing arrow
- * depending on language direction.
- * @return String: HTML "<img>" tag
- */
- protected function downArrow() {
- return $this->arrow( 'd', '-', $this->msg( 'rc-enhanced-hide' )->text() );
- }
-
- /**
- * Generate HTML for a spacer image
- * @return String: HTML "<img>" tag
- */
- protected function spacerArrow() {
- return $this->arrow( '', codepointToUtf8( 0xa0 ) ); // non-breaking space
- }
-
- /**
* Enhanced RC ungrouped line.
*
- * @param $rcObj RecentChange
- * @return String: a HTML formatted line (generated using $r)
+ * @param RecentChange|RCCacheEntry $rcObj
+ * @return string A HTML formatted line (generated using $r)
*/
protected function recentChangesBlockLine( $rcObj ) {
- global $wgRCShowChangedSize;
-
wfProfileIn( __METHOD__ );
$query['curid'] = $rcObj->mAttribs['rc_cur_id'];
@@ -551,10 +488,10 @@ class EnhancedChangesList extends ChangesList {
$classes = array( 'mw-enhanced-rc' );
if ( $logType ) {
# Log entry
-+ $classes[] = Sanitizer::escapeClass( 'mw-changeslist-log-' . $logType );
+ $classes[] = Sanitizer::escapeClass( 'mw-changeslist-log-' . $logType );
} else {
$classes[] = Sanitizer::escapeClass( 'mw-changeslist-ns' .
- $rcObj->mAttribs['rc_namespace'] . '-' . $rcObj->mAttribs['rc_title'] );
+ $rcObj->mAttribs['rc_namespace'] . '-' . $rcObj->mAttribs['rc_title'] );
}
$classes[] = $rcObj->watched && $rcObj->mAttribs['rc_timestamp'] >= $rcObj->watched
? 'mw-changeslist-line-watched' : 'mw-changeslist-line-not-watched';
@@ -563,39 +500,37 @@ class EnhancedChangesList extends ChangesList {
$r .= '<td class="mw-enhanced-rc"><span class="mw-enhancedchanges-arrow-space"></span>';
# Flag and Timestamp
- if ( $type == RC_MOVE || $type == RC_MOVE_OVER_REDIRECT ) {
- $r .= $this->recentChangesFlags( array() ); // no flags, but need the placeholders
- } else {
- $r .= $this->recentChangesFlags( array(
- 'newpage' => $type == RC_NEW,
- 'minor' => $rcObj->mAttribs['rc_minor'],
- 'unpatrolled' => $rcObj->unpatrolled,
- 'bot' => $rcObj->mAttribs['rc_bot'],
- ) );
- }
+ $r .= $this->recentChangesFlags( array(
+ 'newpage' => $type == RC_NEW,
+ 'minor' => $rcObj->mAttribs['rc_minor'],
+ 'unpatrolled' => $rcObj->unpatrolled,
+ 'bot' => $rcObj->mAttribs['rc_bot'],
+ ) );
$r .= '&#160;' . $rcObj->timestamp . '&#160;</td><td>';
# Article or log link
if ( $logType ) {
$logPage = new LogPage( $logType );
$logTitle = SpecialPage::getTitleFor( 'Log', $logType );
$logName = $logPage->getName()->escaped();
- $r .= $this->msg( 'parentheses' )->rawParams( Linker::linkKnown( $logTitle, $logName ) )->escaped();
+ $r .= $this->msg( 'parentheses' )
+ ->rawParams( Linker::linkKnown( $logTitle, $logName ) )->escaped();
} else {
$this->insertArticleLink( $r, $rcObj, $rcObj->unpatrolled, $rcObj->watched );
}
# Diff and hist links
if ( $type != RC_LOG ) {
$query['action'] = 'history';
- $r .= ' ' . $this->msg( 'parentheses' )->rawParams( $rcObj->difflink . $this->message['pipe-separator'] . Linker::linkKnown(
- $rcObj->getTitle(),
- $this->message['hist'],
- array(),
- $query
- ) )->escaped();
+ $r .= ' ' . $this->msg( 'parentheses' )
+ ->rawParams( $rcObj->difflink . $this->message['pipe-separator'] . Linker::linkKnown(
+ $rcObj->getTitle(),
+ $this->message['hist'],
+ array(),
+ $query
+ ) )->escaped();
}
$r .= ' <span class="mw-changeslist-separator">. .</span> ';
# Character diff
- if ( $wgRCShowChangedSize ) {
+ if ( $this->getConfig()->get( 'RCShowChangedSize' ) ) {
$cd = $this->formatCharacterDifference( $rcObj );
if ( $cd !== '' ) {
$r .= $cd . ' <span class="mw-changeslist-separator">. .</span> ';
@@ -629,7 +564,7 @@ class EnhancedChangesList extends ChangesList {
* @return string
*/
protected function recentChangesBlock() {
- if ( count ( $this->rc_cache ) == 0 ) {
+ if ( count( $this->rc_cache ) == 0 ) {
return '';
}
@@ -655,7 +590,6 @@ class EnhancedChangesList extends ChangesList {
* @return string
*/
public function endRecentChangesList() {
- return $this->recentChangesBlock() . parent::endRecentChangesList();
+ return $this->recentChangesBlock() . '</div>';
}
-
}
diff --git a/includes/changes/OldChangesList.php b/includes/changes/OldChangesList.php
index a7fe9342..4eed9262 100644
--- a/includes/changes/OldChangesList.php
+++ b/includes/changes/OldChangesList.php
@@ -19,28 +19,21 @@
*
* @file
*/
+
class OldChangesList extends ChangesList {
/**
* Format a line using the old system (aka without any javascript).
*
- * @param $rc RecentChange, passed by reference
+ * @param RecentChange $rc Passed by reference
* @param bool $watched (default false)
* @param int $linenumber (default null)
*
* @return string|bool
*/
public function recentChangesLine( &$rc, $watched = false, $linenumber = null ) {
- global $wgRCShowChangedSize;
wfProfileIn( __METHOD__ );
- # Should patrol-related stuff be shown?
- $unpatrolled = $this->showAsUnpatrolled( $rc );
-
- $dateheader = ''; // $s now contains only <li>...</li>, for hooks' convenience.
- $this->insertDateHeader( $dateheader, $rc->mAttribs['rc_timestamp'] );
-
- $s = '';
$classes = array();
// use mw-line-even/mw-line-odd class only if linenumber is given (feature from bug 14468)
if ( $linenumber ) {
@@ -56,23 +49,53 @@ class OldChangesList extends ChangesList {
$classes[] = $watched && $rc->mAttribs['rc_timestamp'] >= $watched
? 'mw-changeslist-line-watched' : 'mw-changeslist-line-not-watched';
- // Moved pages (very very old, not supported anymore)
- if ( $rc->mAttribs['rc_type'] == RC_MOVE || $rc->mAttribs['rc_type'] == RC_MOVE_OVER_REDIRECT ) {
- // Log entries
- } elseif ( $rc->mAttribs['rc_log_type'] ) {
+ $html = $this->formatChangeLine( $rc, $classes, $watched );
+
+ if ( $this->watchlist ) {
+ $classes[] = Sanitizer::escapeClass( 'watchlist-' .
+ $rc->mAttribs['rc_namespace'] . '-' . $rc->mAttribs['rc_title'] );
+ }
+
+ if ( !wfRunHooks( 'OldChangesListRecentChangesLine', array( &$this, &$html, $rc, &$classes ) ) ) {
+ wfProfileOut( __METHOD__ );
+
+ return false;
+ }
+
+ wfProfileOut( __METHOD__ );
+
+ $dateheader = ''; // $html now contains only <li>...</li>, for hooks' convenience.
+ $this->insertDateHeader( $dateheader, $rc->mAttribs['rc_timestamp'] );
+
+ return "$dateheader<li class=\"" . implode( ' ', $classes ) . "\">" . $html . "</li>\n";
+ }
+
+ /**
+ * @param RecentChange $rc
+ * @param string[] &$classes
+ * @param boolean $watched
+ *
+ * @return string
+ */
+ private function formatChangeLine( RecentChange $rc, array &$classes, $watched ) {
+ $html = '';
+
+ if ( $rc->mAttribs['rc_log_type'] ) {
$logtitle = SpecialPage::getTitleFor( 'Log', $rc->mAttribs['rc_log_type'] );
- $this->insertLog( $s, $logtitle, $rc->mAttribs['rc_log_type'] );
+ $this->insertLog( $html, $logtitle, $rc->mAttribs['rc_log_type'] );
// Log entries (old format) or log targets, and special pages
} elseif ( $rc->mAttribs['rc_namespace'] == NS_SPECIAL ) {
- list( $name, $subpage ) = SpecialPageFactory::resolveAlias( $rc->mAttribs['rc_title'] );
+ list( $name, $htmlubpage ) = SpecialPageFactory::resolveAlias( $rc->mAttribs['rc_title'] );
if ( $name == 'Log' ) {
- $this->insertLog( $s, $rc->getTitle(), $subpage );
+ $this->insertLog( $html, $rc->getTitle(), $htmlubpage );
}
// Regular entries
} else {
- $this->insertDiffHist( $s, $rc, $unpatrolled );
+ $unpatrolled = $this->showAsUnpatrolled( $rc );
+
+ $this->insertDiffHist( $html, $rc, $unpatrolled );
# M, N, b and ! (minor, new, bot and unpatrolled)
- $s .= $this->recentChangesFlags(
+ $html .= $this->recentChangesFlags(
array(
'newpage' => $rc->mAttribs['rc_type'] == RC_NEW,
'minor' => $rc->mAttribs['rc_minor'],
@@ -81,50 +104,40 @@ class OldChangesList extends ChangesList {
),
''
);
- $this->insertArticleLink( $s, $rc, $unpatrolled, $watched );
+ $this->insertArticleLink( $html, $rc, $unpatrolled, $watched );
}
# Edit/log timestamp
- $this->insertTimestamp( $s, $rc );
+ $this->insertTimestamp( $html, $rc );
# Bytes added or removed
- if ( $wgRCShowChangedSize ) {
+ if ( $this->getConfig()->get( 'RCShowChangedSize' ) ) {
$cd = $this->formatCharacterDifference( $rc );
if ( $cd !== '' ) {
- $s .= $cd . ' <span class="mw-changeslist-separator">. .</span> ';
+ $html .= $cd . ' <span class="mw-changeslist-separator">. .</span> ';
}
}
if ( $rc->mAttribs['rc_type'] == RC_LOG ) {
- $s .= $this->insertLogEntry( $rc );
+ $html .= $this->insertLogEntry( $rc );
} else {
# User tool links
- $this->insertUserRelatedLinks( $s, $rc );
+ $this->insertUserRelatedLinks( $html, $rc );
# LTR/RTL direction mark
- $s .= $this->getLanguage()->getDirMark();
- $s .= $this->insertComment( $rc );
+ $html .= $this->getLanguage()->getDirMark();
+ $html .= $this->insertComment( $rc );
}
# Tags
- $this->insertTags( $s, $rc, $classes );
+ $this->insertTags( $html, $rc, $classes );
# Rollback
- $this->insertRollback( $s, $rc );
+ $this->insertRollback( $html, $rc );
# For subclasses
- $this->insertExtra( $s, $rc, $classes );
+ $this->insertExtra( $html, $rc, $classes );
# How many users watch this page
if ( $rc->numberofWatchingusers > 0 ) {
- $s .= ' ' . $this->numberofWatchingusers( $rc->numberofWatchingusers );
+ $html .= ' ' . $this->numberofWatchingusers( $rc->numberofWatchingusers );
}
- if ( $this->watchlist ) {
- $classes[] = Sanitizer::escapeClass( 'watchlist-' . $rc->mAttribs['rc_namespace'] . '-' . $rc->mAttribs['rc_title'] );
- }
-
- if ( !wfRunHooks( 'OldChangesListRecentChangesLine', array( &$this, &$s, $rc, &$classes ) ) ) {
- wfProfileOut( __METHOD__ );
- return false;
- }
-
- wfProfileOut( __METHOD__ );
- return "$dateheader<li class=\"" . implode( ' ', $classes ) . "\">" . $s . "</li>\n";
+ return $html;
}
}
diff --git a/includes/changes/RCCacheEntry.php b/includes/changes/RCCacheEntry.php
index 9aef3d30..d9cafbc3 100644
--- a/includes/changes/RCCacheEntry.php
+++ b/includes/changes/RCCacheEntry.php
@@ -17,19 +17,27 @@
*
* @file
*/
+
class RCCacheEntry extends RecentChange {
- var $secureName, $link;
- var $curlink, $difflink, $lastlink, $usertalklink, $versionlink;
- var $userlink, $timestamp, $watched;
+ public $curlink;
+ public $difflink;
+ public $lastlink;
+ public $link;
+ public $timestamp;
+ public $unpatrolled;
+ public $userlink;
+ public $usertalklink;
+ public $watched;
/**
- * @param $rc RecentChange
+ * @param RecentChange $rc
* @return RCCacheEntry
*/
static function newFromParent( $rc ) {
$rc2 = new RCCacheEntry;
$rc2->mAttribs = $rc->mAttribs;
$rc2->mExtra = $rc->mExtra;
+
return $rc2;
}
}
diff --git a/includes/changes/RCCacheEntryFactory.php b/includes/changes/RCCacheEntryFactory.php
new file mode 100644
index 00000000..c3fe183e
--- /dev/null
+++ b/includes/changes/RCCacheEntryFactory.php
@@ -0,0 +1,275 @@
+<?php
+/**
+ * Creates a RCCacheEntry from a RecentChange to use in EnhancedChangesList
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ * http://www.gnu.org/copyleft/gpl.html
+ *
+ * @file
+ */
+
+class RCCacheEntryFactory {
+
+ /* @var IContextSource */
+ private $context;
+
+ /* @var string[] */
+ private $messages;
+
+ /**
+ * @param IContextSource $context
+ * @param string[] $messages
+ */
+ public function __construct( IContextSource $context, $messages ) {
+ $this->context = $context;
+ $this->messages = $messages;
+ }
+
+ /**
+ * @param RecentChange $baseRC
+ * @param bool $watched
+ *
+ * @return RCCacheEntry
+ */
+ public function newFromRecentChange( RecentChange $baseRC, $watched ) {
+ $user = $this->context->getUser();
+ $counter = $baseRC->counter;
+
+ $cacheEntry = RCCacheEntry::newFromParent( $baseRC );
+
+ // Should patrol-related stuff be shown?
+ $cacheEntry->unpatrolled = ChangesList::isUnpatrolled( $baseRC, $user );
+
+ $cacheEntry->watched = $cacheEntry->mAttribs['rc_type'] == RC_LOG ? false : $watched;
+ $cacheEntry->numberofWatchingusers = $baseRC->numberofWatchingusers;
+
+ $cacheEntry->link = $this->buildCLink( $cacheEntry );
+ $cacheEntry->timestamp = $this->buildTimestamp( $cacheEntry );
+
+ // Make "cur" and "diff" links. Do not use link(), it is too slow if
+ // called too many times (50% of CPU time on RecentChanges!).
+ $showDiffLinks = $this->showDiffLinks( $cacheEntry, $user );
+
+ $cacheEntry->difflink = $this->buildDiffLink( $cacheEntry, $showDiffLinks, $counter );
+ $cacheEntry->curlink = $this->buildCurLink( $cacheEntry, $showDiffLinks, $counter );
+ $cacheEntry->lastlink = $this->buildLastLink( $cacheEntry, $showDiffLinks );
+
+ // Make user links
+ $cacheEntry->userlink = $this->getUserLink( $cacheEntry );
+
+ if ( !ChangesList::isDeleted( $cacheEntry, Revision::DELETED_USER ) ) {
+ $cacheEntry->usertalklink = Linker::userToolLinks(
+ $cacheEntry->mAttribs['rc_user'],
+ $cacheEntry->mAttribs['rc_user_text']
+ );
+ }
+
+ return $cacheEntry;
+ }
+
+ /**
+ * @param RecentChange $cacheEntry
+ * @param User $user
+ *
+ * @return bool
+ */
+ private function showDiffLinks( RecentChange $cacheEntry, User $user ) {
+ return ChangesList::userCan( $cacheEntry, Revision::DELETED_TEXT, $user );
+ }
+
+ /**
+ * @param RecentChange $cacheEntry
+ *
+ * @return string
+ */
+ private function buildCLink( RecentChange $cacheEntry ) {
+ $type = $cacheEntry->mAttribs['rc_type'];
+
+ // New unpatrolled pages
+ if ( $cacheEntry->unpatrolled && $type == RC_NEW ) {
+ $clink = Linker::linkKnown( $cacheEntry->getTitle() );
+ // Log entries
+ } elseif ( $type == RC_LOG ) {
+ $logType = $cacheEntry->mAttribs['rc_log_type'];
+
+ if ( $logType ) {
+ $clink = $this->getLogLink( $logType );
+ } else {
+ wfDebugLog( 'recentchanges', 'Unexpected log entry with no log type in recent changes' );
+ $clink = Linker::link( $cacheEntry->getTitle() );
+ }
+ // Log entries (old format) and special pages
+ } elseif ( $cacheEntry->mAttribs['rc_namespace'] == NS_SPECIAL ) {
+ wfDebugLog( 'recentchanges', 'Unexpected special page in recentchanges' );
+ $clink = '';
+ // Edits
+ } else {
+ $clink = Linker::linkKnown( $cacheEntry->getTitle() );
+ }
+
+ return $clink;
+ }
+
+ private function getLogLink( $logType ) {
+ $logtitle = SpecialPage::getTitleFor( 'Log', $logType );
+ $logpage = new LogPage( $logType );
+ $logname = $logpage->getName()->escaped();
+
+ $logLink = $this->context->msg( 'parentheses' )
+ ->rawParams( Linker::linkKnown( $logtitle, $logname ) )->escaped();
+
+ return $logLink;
+ }
+
+ /**
+ * @param RecentChange $cacheEntry
+ *
+ * @return string
+ */
+ private function buildTimestamp( RecentChange $cacheEntry ) {
+ return $this->context->getLanguage()->userTime(
+ $cacheEntry->mAttribs['rc_timestamp'],
+ $this->context->getUser()
+ );
+ }
+
+ /**
+ * @param RecentChange $recentChange
+ *
+ * @return array
+ */
+ private function buildCurQueryParams( RecentChange $recentChange ) {
+ return array(
+ 'curid' => $recentChange->mAttribs['rc_cur_id'],
+ 'diff' => 0,
+ 'oldid' => $recentChange->mAttribs['rc_this_oldid']
+ );
+ }
+
+ /**
+ * @param RecentChange $cacheEntry
+ * @param bool $showDiffLinks
+ * @param int $counter
+ *
+ * @return string
+ */
+ private function buildCurLink( RecentChange $cacheEntry, $showDiffLinks, $counter ) {
+ $queryParams = $this->buildCurQueryParams( $cacheEntry );
+ $curMessage = $this->getMessage( 'cur' );
+ $logTypes = array( RC_LOG );
+
+ if ( !$showDiffLinks || in_array( $cacheEntry->mAttribs['rc_type'], $logTypes ) ) {
+ $curLink = $curMessage;
+ } else {
+ $curUrl = htmlspecialchars( $cacheEntry->getTitle()->getLinkURL( $queryParams ) );
+ $curLink = "<a href=\"$curUrl\" tabindex=\"$counter\">$curMessage</a>";
+ }
+
+ return $curLink;
+ }
+
+ /**
+ * @param RecentChange $recentChange
+ *
+ * @return array
+ */
+ private function buildDiffQueryParams( RecentChange $recentChange ) {
+ return array(
+ 'curid' => $recentChange->mAttribs['rc_cur_id'],
+ 'diff' => $recentChange->mAttribs['rc_this_oldid'],
+ 'oldid' => $recentChange->mAttribs['rc_last_oldid']
+ );
+ }
+
+ /**
+ * @param RecentChange $cacheEntry
+ * @param bool $showDiffLinks
+ * @param int $counter
+ *
+ * @return string
+ */
+ private function buildDiffLink( RecentChange $cacheEntry, $showDiffLinks, $counter ) {
+ $queryParams = $this->buildDiffQueryParams( $cacheEntry );
+ $diffMessage = $this->getMessage( 'diff' );
+ $logTypes = array( RC_NEW, RC_LOG );
+
+ if ( !$showDiffLinks ) {
+ $diffLink = $diffMessage;
+ } elseif ( in_array( $cacheEntry->mAttribs['rc_type'], $logTypes ) ) {
+ $diffLink = $diffMessage;
+ } else {
+ $diffUrl = htmlspecialchars( $cacheEntry->getTitle()->getLinkURL( $queryParams ) );
+ $diffLink = "<a href=\"$diffUrl\" tabindex=\"$counter\">$diffMessage</a>";
+ }
+
+ return $diffLink;
+ }
+
+ /**
+ * @param RecentChange $cacheEntry
+ * @param bool $showDiffLinks
+ *
+ * @return string
+ */
+ private function buildLastLink( RecentChange $cacheEntry, $showDiffLinks ) {
+ $lastOldid = $cacheEntry->mAttribs['rc_last_oldid'];
+ $lastMessage = $this->getMessage( 'last' );
+ $type = $cacheEntry->mAttribs['rc_type'];
+ $logTypes = array( RC_LOG );
+
+ // Make "last" link
+ if ( !$showDiffLinks || !$lastOldid || in_array( $type, $logTypes ) ) {
+ $lastLink = $lastMessage;
+ } else {
+ $lastLink = Linker::linkKnown(
+ $cacheEntry->getTitle(),
+ $lastMessage,
+ array(),
+ $this->buildDiffQueryParams( $cacheEntry )
+ );
+ }
+
+ return $lastLink;
+ }
+
+ /**
+ * @param RecentChange $cacheEntry
+ *
+ * @return string
+ */
+ private function getUserLink( RecentChange $cacheEntry ) {
+ if ( ChangesList::isDeleted( $cacheEntry, Revision::DELETED_USER ) ) {
+ $userLink = ' <span class="history-deleted">' .
+ $this->context->msg( 'rev-deleted-user' )->escaped() . '</span>';
+ } else {
+ $userLink = Linker::userLink(
+ $cacheEntry->mAttribs['rc_user'],
+ $cacheEntry->mAttribs['rc_user_text']
+ );
+ }
+
+ return $userLink;
+ }
+
+ /**
+ * @param string $key
+ *
+ * @return string
+ */
+ private function getMessage( $key ) {
+ return $this->messages[$key];
+ }
+
+}
diff --git a/includes/changes/RecentChange.php b/includes/changes/RecentChange.php
index 980bd0a0..e33274e8 100644
--- a/includes/changes/RecentChange.php
+++ b/includes/changes/RecentChange.php
@@ -26,10 +26,10 @@
* mAttribs:
* rc_id id of the row in the recentchanges table
* rc_timestamp time the entry was made
- * rc_cur_time timestamp on the cur row
* rc_namespace namespace #
* rc_title non-prefixed db key
* rc_type is new entry, used to determine whether updating is necessary
+ * rc_source string representation of change source
* rc_minor is minor
* rc_cur_id page_id of associated page entry
* rc_user user id who made the entry
@@ -52,7 +52,6 @@
* mExtra:
* prefixedDBkey prefixed db key, used by external app via msg queue
* lastTimestamp timestamp of previous entry, used in WHERE clause during update
- * lang the interwiki prefix, automatically set in save()
* oldSize text size before the change
* newSize text size after the change
* pageStatus status of the page: created, deleted, moved, restored, changed
@@ -60,59 +59,111 @@
* temporary: not stored in the database
* notificationtimestamp
* numberofWatchingusers
- *
- * @todo document functions and variables
*/
class RecentChange {
- var $mAttribs = array(), $mExtra = array();
+ // Constants for the rc_source field. Extensions may also have
+ // their own source constants.
+ const SRC_EDIT = 'mw.edit';
+ const SRC_NEW = 'mw.new';
+ const SRC_LOG = 'mw.log';
+ const SRC_EXTERNAL = 'mw.external'; // obsolete
+
+ public $mAttribs = array();
+ public $mExtra = array();
/**
* @var Title
*/
- var $mTitle = false;
+ public $mTitle = false;
/**
* @var User
*/
private $mPerformer = false;
+ public $numberofWatchingusers = 0; # Dummy to prevent error message in SpecialRecentChangesLinked
+ public $notificationtimestamp;
+
/**
- * @var Title
+ * @var int Line number of recent change. Default -1.
*/
- var $mMovedToTitle = false;
- var $numberofWatchingusers = 0; # Dummy to prevent error message in SpecialRecentchangeslinked
- var $notificationtimestamp;
+ public $counter = -1;
# Factory methods
/**
- * @param $row
+ * @param mixed $row
* @return RecentChange
*/
public static function newFromRow( $row ) {
$rc = new RecentChange;
$rc->loadFromRow( $row );
+
return $rc;
}
/**
- * @deprecated in 1.22
- * @param $row
- * @return RecentChange
+ * Parsing text to RC_* constants
+ * @since 1.24
+ * @param string|array $type
+ * @throws MWException
+ * @return int|array RC_TYPE
*/
- public static function newFromCurRow( $row ) {
- wfDeprecated( __METHOD__, '1.22' );
- $rc = new RecentChange;
- $rc->loadFromCurRow( $row );
- $rc->notificationtimestamp = false;
- $rc->numberofWatchingusers = false;
- return $rc;
+ public static function parseToRCType( $type ) {
+ if ( is_array( $type ) ) {
+ $retval = array();
+ foreach ( $type as $t ) {
+ $retval[] = RecentChange::parseToRCType( $t );
+ }
+
+ return $retval;
+ }
+
+ switch ( $type ) {
+ case 'edit':
+ return RC_EDIT;
+ case 'new':
+ return RC_NEW;
+ case 'log':
+ return RC_LOG;
+ case 'external':
+ return RC_EXTERNAL;
+ default:
+ throw new MWException( "Unknown type '$type'" );
+ }
+ }
+
+ /**
+ * Parsing RC_* constants to human-readable test
+ * @since 1.24
+ * @param int $rcType
+ * @return string $type
+ */
+ public static function parseFromRCType( $rcType ) {
+ switch ( $rcType ) {
+ case RC_EDIT:
+ $type = 'edit';
+ break;
+ case RC_NEW:
+ $type = 'new';
+ break;
+ case RC_LOG:
+ $type = 'log';
+ break;
+ case RC_EXTERNAL:
+ $type = 'external';
+ break;
+ default:
+ $type = "$rcType";
+ }
+
+ return $type;
}
/**
* Obtain the recent change with a given rc_id value
*
- * @param int $rcid rc_id value to retrieve
+ * @param int $rcid The rc_id value to retrieve
* @return RecentChange
*/
public static function newFromId( $rcid ) {
@@ -122,9 +173,9 @@ class RecentChange {
/**
* Find the first recent change matching some specific conditions
*
- * @param array $conds of conditions
- * @param $fname Mixed: override the method name in profiling/logs
- * @param $options Array Query options
+ * @param array $conds Array of conditions
+ * @param mixed $fname Override the method name in profiling/logs
+ * @param array $options Query options
* @return RecentChange
*/
public static function newFromConds( $conds, $fname = __METHOD__, $options = array() ) {
@@ -146,7 +197,6 @@ class RecentChange {
return array(
'rc_id',
'rc_timestamp',
- 'rc_cur_time',
'rc_user',
'rc_user_text',
'rc_namespace',
@@ -159,6 +209,7 @@ class RecentChange {
'rc_this_oldid',
'rc_last_oldid',
'rc_type',
+ 'rc_source',
'rc_patrolled',
'rc_ip',
'rc_old_len',
@@ -174,27 +225,27 @@ class RecentChange {
# Accessors
/**
- * @param $attribs array
+ * @param array $attribs
*/
public function setAttribs( $attribs ) {
$this->mAttribs = $attribs;
}
/**
- * @param $extra array
+ * @param array $extra
*/
public function setExtra( $extra ) {
$this->mExtra = $extra;
}
/**
- *
* @return Title
*/
public function &getTitle() {
if ( $this->mTitle === false ) {
$this->mTitle = Title::makeTitle( $this->mAttribs['rc_namespace'], $this->mAttribs['rc_title'] );
}
+
return $this->mTitle;
}
@@ -211,21 +262,21 @@ class RecentChange {
$this->mPerformer = User::newFromName( $this->mAttribs['rc_user_text'], false );
}
}
+
return $this->mPerformer;
}
/**
* Writes the data in this object to the database
- * @param $noudp bool
+ * @param bool $noudp
*/
public function save( $noudp = false ) {
- global $wgLocalInterwiki, $wgPutIPinRC, $wgUseEnotif, $wgShowUpdatedMarker, $wgContLang;
+ global $wgPutIPinRC, $wgUseEnotif, $wgShowUpdatedMarker, $wgContLang;
$dbw = wfGetDB( DB_MASTER );
if ( !is_array( $this->mExtra ) ) {
$this->mExtra = array();
}
- $this->mExtra['lang'] = $wgLocalInterwiki;
if ( !$wgPutIPinRC ) {
$this->mAttribs['rc_ip'] = '';
@@ -244,7 +295,6 @@ class RecentChange {
# Fixup database timestamps
$this->mAttribs['rc_timestamp'] = $dbw->timestamp( $this->mAttribs['rc_timestamp'] );
- $this->mAttribs['rc_cur_time'] = $dbw->timestamp( $this->mAttribs['rc_cur_time'] );
$this->mAttribs['rc_id'] = $dbw->nextSequenceValue( 'recentchanges_rc_id_seq' );
## If we are using foreign keys, an entry of 0 for the page_id will fail, so use NULL
@@ -271,7 +321,7 @@ class RecentChange {
$editor = $this->getPerformer();
$title = $this->getTitle();
- if ( wfRunHooks( 'AbortEmailNotification', array( $editor, $title ) ) ) {
+ if ( wfRunHooks( 'AbortEmailNotification', array( $editor, $title, $this ) ) ) {
# @todo FIXME: This would be better as an extension hook
$enotif = new EmailNotification();
$enotif->notifyOnPageChange( $editor, $title,
@@ -285,44 +335,37 @@ class RecentChange {
}
/**
- * @deprecated since 1.22, use notifyRCFeeds instead.
- */
- public function notifyRC2UDP() {
- wfDeprecated( __METHOD__, '1.22' );
- $this->notifyRCFeeds();
- }
-
- /**
- * Send some text to UDP.
- * @deprecated since 1.22
+ * Notify all the feeds about the change.
+ * @param array $feeds Optional feeds to send to, defaults to $wgRCFeeds
*/
- public static function sendToUDP( $line, $address = '', $prefix = '', $port = '' ) {
- global $wgRC2UDPAddress, $wgRC2UDPInterwikiPrefix, $wgRC2UDPPort, $wgRC2UDPPrefix;
-
- wfDeprecated( __METHOD__, '1.22' );
-
- # Assume default for standard RC case
- $address = $address ? $address : $wgRC2UDPAddress;
- $prefix = $prefix ? $prefix : $wgRC2UDPPrefix;
- $port = $port ? $port : $wgRC2UDPPort;
+ public function notifyRCFeeds( array $feeds = null ) {
+ global $wgRCFeeds;
+ if ( $feeds === null ) {
+ $feeds = $wgRCFeeds;
+ }
- $engine = new UDPRCFeedEngine();
- $feed = array(
- 'uri' => "udp://$address:$port/$prefix",
- 'formatter' => 'IRCColourfulRCFeedFormatter',
- 'add_interwiki_prefix' => $wgRC2UDPInterwikiPrefix,
- );
+ $performer = $this->getPerformer();
- return $engine->send( $feed, $line );
- }
+ foreach ( $feeds as $feed ) {
+ $feed += array(
+ 'omit_bots' => false,
+ 'omit_anon' => false,
+ 'omit_user' => false,
+ 'omit_minor' => false,
+ 'omit_patrolled' => false,
+ );
- /**
- * Notify all the feeds about the change.
- */
- public function notifyRCFeeds() {
- global $wgRCFeeds;
+ if (
+ ( $feed['omit_bots'] && $this->mAttribs['rc_bot'] ) ||
+ ( $feed['omit_anon'] && $performer->isAnon() ) ||
+ ( $feed['omit_user'] && !$performer->isAnon() ) ||
+ ( $feed['omit_minor'] && $this->mAttribs['rc_minor'] ) ||
+ ( $feed['omit_patrolled'] && $this->mAttribs['rc_patrolled'] ) ||
+ $this->mAttribs['rc_type'] == RC_EXTERNAL
+ ) {
+ continue;
+ }
- foreach ( $wgRCFeeds as $feed ) {
$engine = self::getEngine( $feed['uri'] );
if ( isset( $this->mExtra['actionCommentIRC'] ) ) {
@@ -331,16 +374,8 @@ class RecentChange {
$actionComment = null;
}
- $omitBots = isset( $feed['omit_bots'] ) ? $feed['omit_bots'] : false;
-
- if (
- ( $omitBots && $this->mAttribs['rc_bot'] ) ||
- $this->mAttribs['rc_type'] == RC_EXTERNAL
- ) {
- continue;
- }
-
- $formatter = new $feed['formatter']();
+ /** @var $formatter RCFeedFormatter */
+ $formatter = is_object( $feed['formatter'] ) ? $feed['formatter'] : new $feed['formatter']();
$line = $formatter->getLine( $feed, $this, $actionComment );
$engine->send( $feed, $line );
@@ -350,10 +385,11 @@ class RecentChange {
/**
* Gets the stream engine object for a given URI from $wgRCEngines
*
- * @param $uri string URI to get the engine object for
- * @return object The engine object
+ * @param string $uri URI to get the engine object for
+ * @throws MWException
+ * @return RCFeedEngine The engine object
*/
- private static function getEngine( $uri ) {
+ public static function getEngine( $uri ) {
global $wgRCEngines;
$scheme = parse_url( $uri, PHP_URL_SCHEME );
@@ -369,19 +405,11 @@ class RecentChange {
}
/**
- * @deprecated since 1.22, moved to IRCColourfulRCFeedFormatter
- */
- public static function cleanupForIRC( $text ) {
- wfDeprecated( __METHOD__, '1.22' );
- return IRCColourfulRCFeedFormatter::cleanupForIRC( $text );
- }
-
- /**
* Mark a given change as patrolled
*
- * @param $change Mixed: RecentChange or corresponding rc_id
- * @param $auto Boolean: for automatic patrol
- * @return Array See doMarkPatrolled(), or null if $change is not an existing rc_id
+ * @param RecentChange|int $change RecentChange or corresponding rc_id
+ * @param bool $auto For automatic patrol
+ * @return array See doMarkPatrolled(), or null if $change is not an existing rc_id
*/
public static function markPatrolled( $change, $auto = false ) {
global $wgUser;
@@ -393,16 +421,18 @@ class RecentChange {
if ( !$change instanceof RecentChange ) {
return null;
}
+
return $change->doMarkPatrolled( $wgUser, $auto );
}
/**
* Mark this RecentChange as patrolled
*
- * NOTE: Can also return 'rcpatroldisabled', 'hookaborted' and 'markedaspatrollederror-noautopatrol' as errors
- * @param $user User object doing the action
- * @param $auto Boolean: for automatic patrol
- * @return array of permissions errors, see Title::getUserPermissionsErrors()
+ * NOTE: Can also return 'rcpatroldisabled', 'hookaborted' and
+ * 'markedaspatrollederror-noautopatrol' as errors
+ * @param User $user User object doing the action
+ * @param bool $auto For automatic patrol
+ * @return array Array of permissions errors, see Title::getUserPermissionsErrors()
*/
public function doMarkPatrolled( User $user, $auto = false ) {
global $wgUseRCPatrol, $wgUseNPPatrol;
@@ -420,7 +450,9 @@ class RecentChange {
}
// Users without the 'autopatrol' right can't patrol their
// own revisions
- if ( $user->getName() == $this->getAttribute( 'rc_user_text' ) && !$user->isAllowed( 'autopatrol' ) ) {
+ if ( $user->getName() == $this->getAttribute( 'rc_user_text' )
+ && !$user->isAllowed( 'autopatrol' )
+ ) {
$errors[] = array( 'markedaspatrollederror-noautopatrol' );
}
if ( $errors ) {
@@ -435,12 +467,13 @@ class RecentChange {
// Log this patrol event
PatrolLog::record( $this, $auto, $user );
wfRunHooks( 'MarkPatrolledComplete', array( $this->getAttribute( 'rc_id' ), &$user, false ) );
+
return array();
}
/**
* Mark this RecentChange patrolled, without error checking
- * @return Integer: number of affected rows
+ * @return int Number of affected rows
*/
public function reallyMarkPatrolled() {
$dbw = wfGetDB( DB_MASTER );
@@ -457,25 +490,26 @@ class RecentChange {
// Invalidate the page cache after the page has been patrolled
// to make sure that the Patrol link isn't visible any longer!
$this->getTitle()->invalidateCache();
+
return $dbw->affectedRows();
}
/**
* Makes an entry in the database corresponding to an edit
*
- * @param $timestamp
- * @param $title Title
- * @param $minor
- * @param $user User
- * @param $comment
- * @param $oldId
- * @param $lastTimestamp
- * @param $bot
- * @param $ip string
- * @param $oldSize int
- * @param $newSize int
- * @param $newId int
- * @param $patrol int
+ * @param string $timestamp
+ * @param Title $title
+ * @param bool $minor
+ * @param User $user
+ * @param string $comment
+ * @param int $oldId
+ * @param string $lastTimestamp
+ * @param bool $bot
+ * @param string $ip
+ * @param int $oldSize
+ * @param int $newSize
+ * @param int $newId
+ * @param int $patrol
* @return RecentChange
*/
public static function notifyEdit( $timestamp, &$title, $minor, &$user, $comment, $oldId,
@@ -484,57 +518,57 @@ class RecentChange {
$rc->mTitle = $title;
$rc->mPerformer = $user;
$rc->mAttribs = array(
- 'rc_timestamp' => $timestamp,
- 'rc_cur_time' => $timestamp,
- 'rc_namespace' => $title->getNamespace(),
- 'rc_title' => $title->getDBkey(),
- 'rc_type' => RC_EDIT,
- 'rc_minor' => $minor ? 1 : 0,
- 'rc_cur_id' => $title->getArticleID(),
- 'rc_user' => $user->getId(),
- 'rc_user_text' => $user->getName(),
- 'rc_comment' => $comment,
+ 'rc_timestamp' => $timestamp,
+ 'rc_namespace' => $title->getNamespace(),
+ 'rc_title' => $title->getDBkey(),
+ 'rc_type' => RC_EDIT,
+ 'rc_source' => self::SRC_EDIT,
+ 'rc_minor' => $minor ? 1 : 0,
+ 'rc_cur_id' => $title->getArticleID(),
+ 'rc_user' => $user->getId(),
+ 'rc_user_text' => $user->getName(),
+ 'rc_comment' => $comment,
'rc_this_oldid' => $newId,
'rc_last_oldid' => $oldId,
- 'rc_bot' => $bot ? 1 : 0,
- 'rc_ip' => self::checkIPAddress( $ip ),
- 'rc_patrolled' => intval( $patrol ),
- 'rc_new' => 0, # obsolete
- 'rc_old_len' => $oldSize,
- 'rc_new_len' => $newSize,
- 'rc_deleted' => 0,
- 'rc_logid' => 0,
- 'rc_log_type' => null,
+ 'rc_bot' => $bot ? 1 : 0,
+ 'rc_ip' => self::checkIPAddress( $ip ),
+ 'rc_patrolled' => intval( $patrol ),
+ 'rc_new' => 0, # obsolete
+ 'rc_old_len' => $oldSize,
+ 'rc_new_len' => $newSize,
+ 'rc_deleted' => 0,
+ 'rc_logid' => 0,
+ 'rc_log_type' => null,
'rc_log_action' => '',
- 'rc_params' => ''
+ 'rc_params' => ''
);
$rc->mExtra = array(
'prefixedDBkey' => $title->getPrefixedDBkey(),
'lastTimestamp' => $lastTimestamp,
- 'oldSize' => $oldSize,
- 'newSize' => $newSize,
- 'pageStatus' => 'changed'
+ 'oldSize' => $oldSize,
+ 'newSize' => $newSize,
+ 'pageStatus' => 'changed'
);
$rc->save();
+
return $rc;
}
/**
* Makes an entry in the database corresponding to page creation
* Note: the title object must be loaded with the new id using resetArticleID()
- * @todo Document parameters and return
*
- * @param $timestamp
- * @param $title Title
- * @param $minor
- * @param $user User
- * @param $comment
- * @param $bot
- * @param $ip string
- * @param $size int
- * @param $newId int
- * @param $patrol int
+ * @param string $timestamp
+ * @param Title $title
+ * @param bool $minor
+ * @param User $user
+ * @param string $comment
+ * @param bool $bot
+ * @param string $ip
+ * @param int $size
+ * @param int $newId
+ * @param int $patrol
* @return RecentChange
*/
public static function notifyNew( $timestamp, &$title, $minor, &$user, $comment, $bot,
@@ -543,29 +577,29 @@ class RecentChange {
$rc->mTitle = $title;
$rc->mPerformer = $user;
$rc->mAttribs = array(
- 'rc_timestamp' => $timestamp,
- 'rc_cur_time' => $timestamp,
- 'rc_namespace' => $title->getNamespace(),
- 'rc_title' => $title->getDBkey(),
- 'rc_type' => RC_NEW,
- 'rc_minor' => $minor ? 1 : 0,
- 'rc_cur_id' => $title->getArticleID(),
- 'rc_user' => $user->getId(),
- 'rc_user_text' => $user->getName(),
- 'rc_comment' => $comment,
- 'rc_this_oldid' => $newId,
- 'rc_last_oldid' => 0,
- 'rc_bot' => $bot ? 1 : 0,
- 'rc_ip' => self::checkIPAddress( $ip ),
- 'rc_patrolled' => intval( $patrol ),
- 'rc_new' => 1, # obsolete
- 'rc_old_len' => 0,
- 'rc_new_len' => $size,
- 'rc_deleted' => 0,
- 'rc_logid' => 0,
- 'rc_log_type' => null,
- 'rc_log_action' => '',
- 'rc_params' => ''
+ 'rc_timestamp' => $timestamp,
+ 'rc_namespace' => $title->getNamespace(),
+ 'rc_title' => $title->getDBkey(),
+ 'rc_type' => RC_NEW,
+ 'rc_source' => self::SRC_NEW,
+ 'rc_minor' => $minor ? 1 : 0,
+ 'rc_cur_id' => $title->getArticleID(),
+ 'rc_user' => $user->getId(),
+ 'rc_user_text' => $user->getName(),
+ 'rc_comment' => $comment,
+ 'rc_this_oldid' => $newId,
+ 'rc_last_oldid' => 0,
+ 'rc_bot' => $bot ? 1 : 0,
+ 'rc_ip' => self::checkIPAddress( $ip ),
+ 'rc_patrolled' => intval( $patrol ),
+ 'rc_new' => 1, # obsolete
+ 'rc_old_len' => 0,
+ 'rc_new_len' => $size,
+ 'rc_deleted' => 0,
+ 'rc_logid' => 0,
+ 'rc_log_type' => null,
+ 'rc_log_action' => '',
+ 'rc_params' => ''
);
$rc->mExtra = array(
@@ -576,28 +610,30 @@ class RecentChange {
'pageStatus' => 'created'
);
$rc->save();
+
return $rc;
}
/**
- * @param $timestamp
- * @param $title
- * @param $user
- * @param $actionComment
- * @param $ip string
- * @param $type
- * @param $action
- * @param $target
- * @param $logComment
- * @param $params
- * @param $newId int
- * @param $actionCommentIRC string
+ * @param string $timestamp
+ * @param Title $title
+ * @param User $user
+ * @param string $actionComment
+ * @param string $ip
+ * @param string $type
+ * @param string $action
+ * @param Title $target
+ * @param string $logComment
+ * @param string $params
+ * @param int $newId
+ * @param string $actionCommentIRC
* @return bool
*/
public static function notifyLog( $timestamp, &$title, &$user, $actionComment, $ip, $type,
- $action, $target, $logComment, $params, $newId = 0, $actionCommentIRC = '' )
- {
+ $action, $target, $logComment, $params, $newId = 0, $actionCommentIRC = ''
+ ) {
global $wgLogRestrictions;
+
# Don't add private logs to RC!
if ( isset( $wgLogRestrictions[$type] ) && $wgLogRestrictions[$type] != '*' ) {
return false;
@@ -605,22 +641,23 @@ class RecentChange {
$rc = self::newLogEntry( $timestamp, $title, $user, $actionComment, $ip, $type, $action,
$target, $logComment, $params, $newId, $actionCommentIRC );
$rc->save();
+
return true;
}
/**
- * @param $timestamp
- * @param $title Title
- * @param $user User
- * @param $actionComment
- * @param $ip string
- * @param $type
- * @param $action
- * @param $target Title
- * @param $logComment
- * @param $params
- * @param $newId int
- * @param $actionCommentIRC string
+ * @param string $timestamp
+ * @param Title $title
+ * @param User $user
+ * @param string $actionComment
+ * @param string $ip
+ * @param string $type
+ * @param string $action
+ * @param Title $target
+ * @param string $logComment
+ * @param string $params
+ * @param int $newId
+ * @param string $actionCommentIRC
* @return RecentChange
*/
public static function newLogEntry( $timestamp, &$title, &$user, $actionComment, $ip,
@@ -652,45 +689,46 @@ class RecentChange {
$rc->mTitle = $target;
$rc->mPerformer = $user;
$rc->mAttribs = array(
- 'rc_timestamp' => $timestamp,
- 'rc_cur_time' => $timestamp,
- 'rc_namespace' => $target->getNamespace(),
- 'rc_title' => $target->getDBkey(),
- 'rc_type' => RC_LOG,
- 'rc_minor' => 0,
- 'rc_cur_id' => $target->getArticleID(),
- 'rc_user' => $user->getId(),
- 'rc_user_text' => $user->getName(),
- 'rc_comment' => $logComment,
+ 'rc_timestamp' => $timestamp,
+ 'rc_namespace' => $target->getNamespace(),
+ 'rc_title' => $target->getDBkey(),
+ 'rc_type' => RC_LOG,
+ 'rc_source' => self::SRC_LOG,
+ 'rc_minor' => 0,
+ 'rc_cur_id' => $target->getArticleID(),
+ 'rc_user' => $user->getId(),
+ 'rc_user_text' => $user->getName(),
+ 'rc_comment' => $logComment,
'rc_this_oldid' => 0,
'rc_last_oldid' => 0,
- 'rc_bot' => $user->isAllowed( 'bot' ) ? $wgRequest->getBool( 'bot', true ) : 0,
- 'rc_ip' => self::checkIPAddress( $ip ),
- 'rc_patrolled' => 1,
- 'rc_new' => 0, # obsolete
- 'rc_old_len' => null,
- 'rc_new_len' => null,
- 'rc_deleted' => 0,
- 'rc_logid' => $newId,
- 'rc_log_type' => $type,
+ 'rc_bot' => $user->isAllowed( 'bot' ) ? $wgRequest->getBool( 'bot', true ) : 0,
+ 'rc_ip' => self::checkIPAddress( $ip ),
+ 'rc_patrolled' => 1,
+ 'rc_new' => 0, # obsolete
+ 'rc_old_len' => null,
+ 'rc_new_len' => null,
+ 'rc_deleted' => 0,
+ 'rc_logid' => $newId,
+ 'rc_log_type' => $type,
'rc_log_action' => $action,
- 'rc_params' => $params
+ 'rc_params' => $params
);
$rc->mExtra = array(
'prefixedDBkey' => $title->getPrefixedDBkey(),
'lastTimestamp' => 0,
'actionComment' => $actionComment, // the comment appended to the action, passed from LogPage
- 'pageStatus' => $pageStatus,
+ 'pageStatus' => $pageStatus,
'actionCommentIRC' => $actionCommentIRC
);
+
return $rc;
}
/**
* Initialises the members of this object from a mysql row object
*
- * @param $row
+ * @param mixed $row
*/
public function loadFromRow( $row ) {
$this->mAttribs = get_object_vars( $row );
@@ -699,42 +737,6 @@ class RecentChange {
}
/**
- * Makes a pseudo-RC entry from a cur row
- *
- * @deprected in 1.22
- * @param $row
- */
- public function loadFromCurRow( $row ) {
- wfDeprecated( __METHOD__, '1.22' );
- $this->mAttribs = array(
- 'rc_timestamp' => wfTimestamp( TS_MW, $row->rev_timestamp ),
- 'rc_cur_time' => $row->rev_timestamp,
- 'rc_user' => $row->rev_user,
- 'rc_user_text' => $row->rev_user_text,
- 'rc_namespace' => $row->page_namespace,
- 'rc_title' => $row->page_title,
- 'rc_comment' => $row->rev_comment,
- 'rc_minor' => $row->rev_minor_edit ? 1 : 0,
- 'rc_type' => $row->page_is_new ? RC_NEW : RC_EDIT,
- 'rc_cur_id' => $row->page_id,
- 'rc_this_oldid' => $row->rev_id,
- 'rc_last_oldid' => isset( $row->rc_last_oldid ) ? $row->rc_last_oldid : 0,
- 'rc_bot' => 0,
- 'rc_ip' => '',
- 'rc_id' => $row->rc_id,
- 'rc_patrolled' => $row->rc_patrolled,
- 'rc_new' => $row->page_is_new, # obsolete
- 'rc_old_len' => $row->rc_old_len,
- 'rc_new_len' => $row->rc_new_len,
- 'rc_params' => isset( $row->rc_params ) ? $row->rc_params : '',
- 'rc_log_type' => isset( $row->rc_log_type ) ? $row->rc_log_type : null,
- 'rc_log_action' => isset( $row->rc_log_action ) ? $row->rc_log_action : null,
- 'rc_logid' => isset( $row->rc_logid ) ? $row->rc_logid : 0,
- 'rc_deleted' => $row->rc_deleted // MUST be set
- );
- }
-
- /**
* Get an attribute value
*
* @param string $name Attribute name
@@ -754,7 +756,7 @@ class RecentChange {
/**
* Gets the end part of the diff URL associated with this object
* Blank if no diff link should be displayed
- * @param $forceCur
+ * @param bool $forceCur
* @return string
*/
public function diffLinkTrail( $forceCur ) {
@@ -769,14 +771,15 @@ class RecentChange {
} else {
$trail = '';
}
+
return $trail;
}
/**
* Returns the change size (HTML).
* The lengths can be given optionally.
- * @param $old int
- * @param $new int
+ * @param int $old
+ * @param int $new
* @return string
*/
public function getCharacterDifference( $old = 0, $new = 0 ) {
@@ -789,6 +792,7 @@ class RecentChange {
if ( $old === null || $new === null ) {
return '';
}
+
return ChangesList::showCharacterDifference( $old, $new );
}
@@ -803,7 +807,7 @@ class RecentChange {
$method = __METHOD__;
$dbw = wfGetDB( DB_MASTER );
- $dbw->onTransactionIdle( function() use ( $dbw, $method ) {
+ $dbw->onTransactionIdle( function () use ( $dbw, $method ) {
global $wgRCMaxAge;
$cutoff = $dbw->timestamp( time() - $wgRCMaxAge );
@@ -819,7 +823,8 @@ class RecentChange {
global $wgRequest;
if ( $ip ) {
if ( !IP::isIPAddress( $ip ) ) {
- throw new MWException( "Attempt to write \"" . $ip . "\" as an IP address into recent changes" );
+ throw new MWException( "Attempt to write \"" . $ip .
+ "\" as an IP address into recent changes" );
}
} else {
$ip = $wgRequest->getIP();
@@ -827,6 +832,7 @@ class RecentChange {
$ip = '';
}
}
+
return $ip;
}
@@ -835,12 +841,13 @@ class RecentChange {
* as the recentchanges table might not be cleared out regularly (so older entries might exist)
* or rows which will be deleted soon shouldn't be included.
*
- * @param $timestamp mixed MWTimestamp compatible timestamp
- * @param $tolerance integer Tolerance in seconds
+ * @param mixed $timestamp MWTimestamp compatible timestamp
+ * @param int $tolerance Tolerance in seconds
* @return bool
*/
public static function isInRCLifespan( $timestamp, $tolerance = 0 ) {
global $wgRCMaxAge;
+
return wfTimestamp( TS_UNIX, $timestamp ) > time() - $tolerance - $wgRCMaxAge;
}
}