summaryrefslogtreecommitdiff
path: root/includes/changes/ChangesList.php
diff options
context:
space:
mode:
Diffstat (limited to 'includes/changes/ChangesList.php')
-rw-r--r--includes/changes/ChangesList.php250
1 files changed, 147 insertions, 103 deletions
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;
}
}