2004-11-25 13:47:17 +00:00
|
|
|
<?php
|
2010-08-14 17:42:40 +00:00
|
|
|
/**
|
2013-10-17 00:51:49 +00:00
|
|
|
* Generates a list of changes using an Enhanced system (uses javascript).
|
2010-08-14 17:42:40 +00:00
|
|
|
*
|
2012-05-21 19:56:04 +00:00
|
|
|
* 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
|
|
|
|
|
*
|
2010-08-14 17:42:40 +00:00
|
|
|
* @file
|
|
|
|
|
*/
|
2004-11-25 13:47:17 +00:00
|
|
|
|
2005-09-06 18:43:45 +00:00
|
|
|
class EnhancedChangesList extends ChangesList {
|
2013-11-26 11:56:17 +00:00
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @var RCCacheEntryFactory
|
|
|
|
|
*/
|
|
|
|
|
protected $cacheEntryFactory;
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @var array Array of array of RCCacheEntry
|
|
|
|
|
*/
|
2012-01-12 19:03:32 +00:00
|
|
|
protected $rc_cache;
|
|
|
|
|
|
2017-05-16 22:43:35 +00:00
|
|
|
/**
|
|
|
|
|
* @var TemplateParser
|
|
|
|
|
*/
|
|
|
|
|
protected $templateParser;
|
|
|
|
|
|
2013-11-26 11:56:17 +00:00
|
|
|
/**
|
|
|
|
|
* @param IContextSource|Skin $obj
|
Back-end of new RecentChanges page, refactoring
Generate old RC, Related changes (it was already displayed and working
on 'Related changes' before this change), and Watchlist/etc. and data
for new UI from back-end.
This moves everything used for defining the old (unstructured) and new
(structured) filters into unified objects, ChangesListFilter and
ChangesListFilterGroup (and sub-classes).
This includes the query logic (see below) and logic for adding
CSS attribution classes.
This is a breaking change (for subclasses of ChangesListSpecialpage)
due to the signature (and name) change of buildMainQueryConds and
doMainQuery. An alternative that I don't think is a breaking change
would be to put the filter->DB logic in runMainQueryHook, but then it's
doing more than just running a hook.
This is because it used to only build $conds here, but it's clear from
filterOnUserExperienceLevel filters need more than this. I added all
the DB parameters from the hook, but this could be debated.
I have an checked and fixed the WMF-deployed extensions affected by
this.
Other than that, there should be full back-compat (including legacy
filters not using the new system).
* add hidepatrolled/hideunpatrolled to new UI.
* Move userExpLevel from RC to ChangesListSpecialPage. Although for
now the structured UI only displays on RC anyway, when it displays on
watchlist, it seems we'll want userExpLevel there.
Change this to make 'all' exclude unregistered users.
* Don't have front-end convert none-selected to 'all' on string_options.
* Needs the hideanons/hideliu special redirect to be done before this
is merged (T151873)
Bug: T152754
Bug: T152797
Change-Id: Iec2d82f6a830403d1c948a280efa58992e0cdee7
2017-02-14 07:55:37 +00:00
|
|
|
* @param array $filterGroups Array of ChangesListFilterGroup objects (currently optional)
|
2014-12-24 13:49:20 +00:00
|
|
|
* @throws MWException
|
2013-11-26 11:56:17 +00:00
|
|
|
*/
|
Back-end of new RecentChanges page, refactoring
Generate old RC, Related changes (it was already displayed and working
on 'Related changes' before this change), and Watchlist/etc. and data
for new UI from back-end.
This moves everything used for defining the old (unstructured) and new
(structured) filters into unified objects, ChangesListFilter and
ChangesListFilterGroup (and sub-classes).
This includes the query logic (see below) and logic for adding
CSS attribution classes.
This is a breaking change (for subclasses of ChangesListSpecialpage)
due to the signature (and name) change of buildMainQueryConds and
doMainQuery. An alternative that I don't think is a breaking change
would be to put the filter->DB logic in runMainQueryHook, but then it's
doing more than just running a hook.
This is because it used to only build $conds here, but it's clear from
filterOnUserExperienceLevel filters need more than this. I added all
the DB parameters from the hook, but this could be debated.
I have an checked and fixed the WMF-deployed extensions affected by
this.
Other than that, there should be full back-compat (including legacy
filters not using the new system).
* add hidepatrolled/hideunpatrolled to new UI.
* Move userExpLevel from RC to ChangesListSpecialPage. Although for
now the structured UI only displays on RC anyway, when it displays on
watchlist, it seems we'll want userExpLevel there.
Change this to make 'all' exclude unregistered users.
* Don't have front-end convert none-selected to 'all' on string_options.
* Needs the hideanons/hideliu special redirect to be done before this
is merged (T151873)
Bug: T152754
Bug: T152797
Change-Id: Iec2d82f6a830403d1c948a280efa58992e0cdee7
2017-02-14 07:55:37 +00:00
|
|
|
public function __construct( $obj, array $filterGroups = [] ) {
|
2013-11-26 11:56:17 +00:00
|
|
|
if ( $obj instanceof Skin ) {
|
|
|
|
|
// @todo: deprecate constructing with Skin
|
|
|
|
|
$context = $obj->getContext();
|
|
|
|
|
} else {
|
2014-07-21 12:47:42 +00:00
|
|
|
if ( !$obj instanceof IContextSource ) {
|
2013-11-26 11:56:17 +00:00
|
|
|
throw new MWException( 'EnhancedChangesList must be constructed with a '
|
|
|
|
|
. 'context source or skin.' );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
$context = $obj;
|
|
|
|
|
}
|
|
|
|
|
|
Back-end of new RecentChanges page, refactoring
Generate old RC, Related changes (it was already displayed and working
on 'Related changes' before this change), and Watchlist/etc. and data
for new UI from back-end.
This moves everything used for defining the old (unstructured) and new
(structured) filters into unified objects, ChangesListFilter and
ChangesListFilterGroup (and sub-classes).
This includes the query logic (see below) and logic for adding
CSS attribution classes.
This is a breaking change (for subclasses of ChangesListSpecialpage)
due to the signature (and name) change of buildMainQueryConds and
doMainQuery. An alternative that I don't think is a breaking change
would be to put the filter->DB logic in runMainQueryHook, but then it's
doing more than just running a hook.
This is because it used to only build $conds here, but it's clear from
filterOnUserExperienceLevel filters need more than this. I added all
the DB parameters from the hook, but this could be debated.
I have an checked and fixed the WMF-deployed extensions affected by
this.
Other than that, there should be full back-compat (including legacy
filters not using the new system).
* add hidepatrolled/hideunpatrolled to new UI.
* Move userExpLevel from RC to ChangesListSpecialPage. Although for
now the structured UI only displays on RC anyway, when it displays on
watchlist, it seems we'll want userExpLevel there.
Change this to make 'all' exclude unregistered users.
* Don't have front-end convert none-selected to 'all' on string_options.
* Needs the hideanons/hideliu special redirect to be done before this
is merged (T151873)
Bug: T152754
Bug: T152797
Change-Id: Iec2d82f6a830403d1c948a280efa58992e0cdee7
2017-02-14 07:55:37 +00:00
|
|
|
parent::__construct( $context, $filterGroups );
|
2013-11-26 11:56:17 +00:00
|
|
|
|
|
|
|
|
// message is set by the parent ChangesList class
|
|
|
|
|
$this->cacheEntryFactory = new RCCacheEntryFactory(
|
|
|
|
|
$context,
|
2016-05-13 07:24:29 +00:00
|
|
|
$this->message,
|
|
|
|
|
$this->linkRenderer
|
2013-11-26 11:56:17 +00:00
|
|
|
);
|
2017-05-16 22:43:35 +00:00
|
|
|
$this->templateParser = new TemplateParser();
|
2013-11-26 11:56:17 +00:00
|
|
|
}
|
|
|
|
|
|
2008-10-25 20:57:56 +00:00
|
|
|
/**
|
2010-01-05 21:24:23 +00:00
|
|
|
* Add the JavaScript file for enhanced changeslist
|
2013-11-19 12:25:54 +00:00
|
|
|
* @return string
|
2010-01-05 21:24:23 +00:00
|
|
|
*/
|
2014-03-26 14:07:44 +00:00
|
|
|
public function beginRecentChangesList() {
|
2016-02-17 09:09:32 +00:00
|
|
|
$this->rc_cache = [];
|
2008-10-25 20:57:56 +00:00
|
|
|
$this->rcMoveIndex = 0;
|
|
|
|
|
$this->rcCacheIndex = 0;
|
|
|
|
|
$this->lastdate = '';
|
|
|
|
|
$this->rclistOpen = false;
|
2016-02-17 09:09:32 +00:00
|
|
|
$this->getOutput()->addModuleStyles( [
|
2013-06-13 23:47:43 +00:00
|
|
|
'mediawiki.special.changeslist',
|
|
|
|
|
'mediawiki.special.changeslist.enhanced',
|
2016-02-17 09:09:32 +00:00
|
|
|
] );
|
|
|
|
|
$this->getOutput()->addModules( [
|
2013-06-13 23:47:43 +00:00
|
|
|
'jquery.makeCollapsible',
|
|
|
|
|
'mediawiki.icon',
|
2016-02-17 09:09:32 +00:00
|
|
|
] );
|
2013-11-08 11:20:58 +00:00
|
|
|
|
2013-11-26 22:13:51 +00:00
|
|
|
return '<div class="mw-changeslist">';
|
2008-10-25 20:57:56 +00:00
|
|
|
}
|
2013-11-08 11:20:58 +00:00
|
|
|
|
2005-09-06 18:14:24 +00:00
|
|
|
/**
|
|
|
|
|
* Format a line for enhanced recentchange (aka with javascript and block of lines).
|
2011-04-04 21:23:22 +00:00
|
|
|
*
|
2015-10-13 09:56:04 +00:00
|
|
|
* @param RecentChange $rc
|
2013-11-19 12:25:54 +00:00
|
|
|
* @param bool $watched
|
2015-10-13 09:56:04 +00:00
|
|
|
* @param int $linenumber (default null)
|
2011-05-20 22:03:10 +00:00
|
|
|
*
|
|
|
|
|
* @return string
|
2005-09-06 18:14:24 +00:00
|
|
|
*/
|
2015-10-13 09:56:04 +00:00
|
|
|
public function recentChangesLine( &$rc, $watched = false, $linenumber = null ) {
|
2013-11-08 11:20:58 +00:00
|
|
|
$date = $this->getLanguage()->userDate(
|
2015-10-13 09:56:04 +00:00
|
|
|
$rc->mAttribs['rc_timestamp'],
|
2013-11-08 11:20:58 +00:00
|
|
|
$this->getUser()
|
|
|
|
|
);
|
2017-07-20 18:38:52 +00:00
|
|
|
if ( $this->lastdate === '' ) {
|
|
|
|
|
$this->lastdate = $date;
|
|
|
|
|
}
|
2013-11-08 11:20:58 +00:00
|
|
|
|
2004-11-25 13:47:17 +00:00
|
|
|
$ret = '';
|
2013-11-08 11:20:58 +00:00
|
|
|
|
2017-07-20 18:38:52 +00:00
|
|
|
# If it's a new day, flush the cache and update $this->lastdate
|
|
|
|
|
if ( $date !== $this->lastdate ) {
|
|
|
|
|
# Process current cache (uses $this->lastdate to generate a heading)
|
2005-12-16 23:56:44 +00:00
|
|
|
$ret = $this->recentChangesBlock();
|
2016-02-17 09:09:32 +00:00
|
|
|
$this->rc_cache = [];
|
2004-11-25 13:47:17 +00:00
|
|
|
$this->lastdate = $date;
|
|
|
|
|
}
|
2005-07-01 20:36:04 +00:00
|
|
|
|
2015-10-13 09:56:04 +00:00
|
|
|
$cacheEntry = $this->cacheEntryFactory->newFromRecentChange( $rc, $watched );
|
2014-04-08 08:40:04 +00:00
|
|
|
$this->addCacheEntry( $cacheEntry );
|
2004-11-25 13:47:17 +00:00
|
|
|
|
2014-04-08 08:40:04 +00:00
|
|
|
return $ret;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Put accumulated information into the cache, for later display.
|
|
|
|
|
* Page moves go on their own line.
|
|
|
|
|
*
|
|
|
|
|
* @param RCCacheEntry $cacheEntry
|
|
|
|
|
*/
|
|
|
|
|
protected function addCacheEntry( RCCacheEntry $cacheEntry ) {
|
2014-04-11 10:35:42 +00:00
|
|
|
$cacheGroupingKey = $this->makeCacheGroupingKey( $cacheEntry );
|
|
|
|
|
|
|
|
|
|
if ( !isset( $this->rc_cache[$cacheGroupingKey] ) ) {
|
2016-02-17 09:09:32 +00:00
|
|
|
$this->rc_cache[$cacheGroupingKey] = [];
|
2014-04-11 10:35:42 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
array_push( $this->rc_cache[$cacheGroupingKey], $cacheEntry );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @todo use rc_source to group, if set; fallback to rc_type
|
|
|
|
|
*
|
|
|
|
|
* @param RCCacheEntry $cacheEntry
|
|
|
|
|
*
|
|
|
|
|
* @return string
|
|
|
|
|
*/
|
|
|
|
|
protected function makeCacheGroupingKey( RCCacheEntry $cacheEntry ) {
|
2013-11-08 11:20:58 +00:00
|
|
|
$title = $cacheEntry->getTitle();
|
2014-04-11 10:35:42 +00:00
|
|
|
$cacheGroupingKey = $title->getPrefixedDBkey();
|
2013-11-08 11:20:58 +00:00
|
|
|
|
2013-11-26 11:56:17 +00:00
|
|
|
$type = $cacheEntry->mAttribs['rc_type'];
|
|
|
|
|
|
2014-06-05 00:54:02 +00:00
|
|
|
if ( $type == RC_LOG ) {
|
2014-04-11 10:35:42 +00:00
|
|
|
// Group by log type
|
|
|
|
|
$cacheGroupingKey = SpecialPage::getTitleFor(
|
|
|
|
|
'Log',
|
|
|
|
|
$cacheEntry->mAttribs['rc_log_type']
|
|
|
|
|
)->getPrefixedDBkey();
|
2004-11-25 13:47:17 +00:00
|
|
|
}
|
2014-04-11 10:35:42 +00:00
|
|
|
|
|
|
|
|
return $cacheGroupingKey;
|
2004-11-25 13:47:17 +00:00
|
|
|
}
|
2006-01-07 13:31:29 +00:00
|
|
|
|
2005-09-06 22:16:41 +00:00
|
|
|
/**
|
|
|
|
|
* Enhanced RC group
|
2013-11-19 12:25:54 +00:00
|
|
|
* @param RCCacheEntry[] $block
|
2012-02-09 21:33:27 +00:00
|
|
|
* @return string
|
2016-03-23 15:25:44 +00:00
|
|
|
* @throws DomainException
|
2005-09-06 22:16:41 +00:00
|
|
|
*/
|
2008-04-04 13:16:58 +00:00
|
|
|
protected function recentChangesBlockGroup( $block ) {
|
2016-03-23 15:25:44 +00:00
|
|
|
$recentChangesFlags = $this->getConfig()->get( 'RecentChangesFlags' );
|
2009-02-20 13:00:58 +00:00
|
|
|
|
2010-11-08 21:21:32 +00:00
|
|
|
# Add the namespace and title of the block as part of the class
|
2016-02-17 09:09:32 +00:00
|
|
|
$tableClasses = [ 'mw-collapsible', 'mw-collapsed', 'mw-enhanced-rc' ];
|
2010-11-08 21:21:32 +00:00
|
|
|
if ( $block[0]->mAttribs['rc_log_type'] ) {
|
|
|
|
|
# Log entry
|
2015-10-19 08:33:54 +00:00
|
|
|
$tableClasses[] = Sanitizer::escapeClass( 'mw-changeslist-log-'
|
2014-01-14 06:19:21 +00:00
|
|
|
. $block[0]->mAttribs['rc_log_type'] );
|
2010-11-08 21:21:32 +00:00
|
|
|
} else {
|
2015-10-19 08:33:54 +00:00
|
|
|
$tableClasses[] = Sanitizer::escapeClass( 'mw-changeslist-ns'
|
2013-11-18 22:07:49 +00:00
|
|
|
. $block[0]->mAttribs['rc_namespace'] . '-' . $block[0]->mAttribs['rc_title'] );
|
2010-11-08 21:21:32 +00:00
|
|
|
}
|
2015-10-19 08:33:54 +00:00
|
|
|
if ( $block[0]->watched
|
|
|
|
|
&& $block[0]->mAttribs['rc_timestamp'] >= $block[0]->watched
|
|
|
|
|
) {
|
|
|
|
|
$tableClasses[] = 'mw-changeslist-line-watched';
|
|
|
|
|
} else {
|
|
|
|
|
$tableClasses[] = 'mw-changeslist-line-not-watched';
|
|
|
|
|
}
|
2005-09-06 22:16:41 +00:00
|
|
|
|
|
|
|
|
# Collate list of users
|
2016-02-17 09:09:32 +00:00
|
|
|
$userlinks = [];
|
2008-04-01 22:41:19 +00:00
|
|
|
# Other properties
|
2015-02-26 13:10:22 +00:00
|
|
|
$curId = 0;
|
2008-04-01 22:41:19 +00:00
|
|
|
# Some catalyst variables...
|
2008-03-16 18:46:09 +00:00
|
|
|
$namehidden = true;
|
2008-12-11 21:34:15 +00:00
|
|
|
$allLogs = true;
|
2014-08-22 20:01:08 +00:00
|
|
|
$RCShowChangedSize = $this->getConfig()->get( 'RCShowChangedSize' );
|
2016-03-23 15:25:44 +00:00
|
|
|
|
|
|
|
|
# Default values for RC flags
|
|
|
|
|
$collectedRcFlags = [];
|
|
|
|
|
foreach ( $recentChangesFlags as $key => $value ) {
|
|
|
|
|
$flagGrouping = ( isset( $recentChangesFlags[$key]['grouping'] ) ?
|
|
|
|
|
$recentChangesFlags[$key]['grouping'] : 'any' );
|
|
|
|
|
switch ( $flagGrouping ) {
|
|
|
|
|
case 'all':
|
|
|
|
|
$collectedRcFlags[$key] = true;
|
|
|
|
|
break;
|
|
|
|
|
case 'any':
|
|
|
|
|
$collectedRcFlags[$key] = false;
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
throw new DomainException( "Unknown grouping type \"{$flagGrouping}\"" );
|
2005-09-06 22:16:41 +00:00
|
|
|
}
|
2016-03-23 15:25:44 +00:00
|
|
|
}
|
|
|
|
|
foreach ( $block as $rcObj ) {
|
2008-03-16 18:46:09 +00:00
|
|
|
// If all log actions to this page were hidden, then don't
|
|
|
|
|
// give the name of the affected page for this block!
|
2013-04-20 22:49:30 +00:00
|
|
|
if ( !$this->isDeleted( $rcObj, LogPage::DELETED_ACTION ) ) {
|
2008-03-16 18:46:09 +00:00
|
|
|
$namehidden = false;
|
|
|
|
|
}
|
2005-12-16 23:56:44 +00:00
|
|
|
$u = $rcObj->userlink;
|
2013-04-20 22:49:30 +00:00
|
|
|
if ( !isset( $userlinks[$u] ) ) {
|
2005-12-16 23:56:44 +00:00
|
|
|
$userlinks[$u] = 0;
|
2005-09-06 22:16:41 +00:00
|
|
|
}
|
2013-04-20 22:49:30 +00:00
|
|
|
if ( $rcObj->mAttribs['rc_type'] != RC_LOG ) {
|
2008-12-11 21:34:15 +00:00
|
|
|
$allLogs = false;
|
2008-04-01 22:41:19 +00:00
|
|
|
}
|
|
|
|
|
# Get the latest entry with a page_id and oldid
|
|
|
|
|
# since logs may not have these.
|
2013-04-20 22:49:30 +00:00
|
|
|
if ( !$curId && $rcObj->mAttribs['rc_cur_id'] ) {
|
2008-04-01 22:41:19 +00:00
|
|
|
$curId = $rcObj->mAttribs['rc_cur_id'];
|
|
|
|
|
}
|
2008-04-14 07:45:50 +00:00
|
|
|
|
2005-12-16 23:56:44 +00:00
|
|
|
$userlinks[$u]++;
|
2005-09-06 22:16:41 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
# Sort the list and convert to text
|
2005-12-16 23:56:44 +00:00
|
|
|
krsort( $userlinks );
|
|
|
|
|
asort( $userlinks );
|
2016-02-17 09:09:32 +00:00
|
|
|
$users = [];
|
2013-04-20 22:49:30 +00:00
|
|
|
foreach ( $userlinks as $userlink => $count ) {
|
2005-09-06 22:16:41 +00:00
|
|
|
$text = $userlink;
|
2011-11-21 16:13:21 +00:00
|
|
|
$text .= $this->getLanguage()->getDirMark();
|
2013-04-20 22:49:30 +00:00
|
|
|
if ( $count > 1 ) {
|
2017-06-05 15:06:31 +00:00
|
|
|
$formattedCount = $this->msg( 'ntimes' )->numParams( $count )->escaped();
|
2013-11-18 22:03:29 +00:00
|
|
|
$text .= ' ' . $this->msg( 'parentheses' )->rawParams( $formattedCount )->escaped();
|
2005-12-16 23:56:44 +00:00
|
|
|
}
|
|
|
|
|
array_push( $users, $text );
|
2005-09-06 22:16:41 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
# Article link
|
2015-10-19 08:33:54 +00:00
|
|
|
$articleLink = '';
|
|
|
|
|
$revDeletedMsg = false;
|
2013-04-20 22:49:30 +00:00
|
|
|
if ( $namehidden ) {
|
2015-10-19 08:33:54 +00:00
|
|
|
$revDeletedMsg = $this->msg( 'rev-deleted-event' )->escaped();
|
2013-04-20 22:49:30 +00:00
|
|
|
} elseif ( $allLogs ) {
|
2015-10-19 08:33:54 +00:00
|
|
|
$articleLink = $this->maybeWatchedLink( $block[0]->link, $block[0]->watched );
|
2008-04-01 22:41:19 +00:00
|
|
|
} else {
|
2015-10-19 08:33:54 +00:00
|
|
|
$articleLink = $this->getArticleLink( $block[0], $block[0]->unpatrolled, $block[0]->watched );
|
2008-04-01 22:41:19 +00:00
|
|
|
}
|
2007-02-28 18:11:09 +00:00
|
|
|
|
2009-06-06 22:42:48 +00:00
|
|
|
$queryParams['curid'] = $curId;
|
2013-07-24 11:45:17 +00:00
|
|
|
|
2015-09-16 10:44:04 +00:00
|
|
|
# Sub-entries
|
2016-02-17 09:09:32 +00:00
|
|
|
$lines = [];
|
2015-09-16 10:44:04 +00:00
|
|
|
foreach ( $block as $i => $rcObj ) {
|
|
|
|
|
$line = $this->getLineData( $block, $rcObj, $queryParams );
|
|
|
|
|
if ( !$line ) {
|
|
|
|
|
// completely ignore this RC entry if we don't want to render it
|
|
|
|
|
unset( $block[$i] );
|
2016-05-04 14:47:03 +00:00
|
|
|
continue;
|
2015-09-16 10:44:04 +00:00
|
|
|
}
|
2016-03-23 15:25:44 +00:00
|
|
|
|
|
|
|
|
// Roll up flags
|
|
|
|
|
foreach ( $line['recentChangesFlagsRaw'] as $key => $value ) {
|
|
|
|
|
$flagGrouping = ( isset( $recentChangesFlags[$key]['grouping'] ) ?
|
|
|
|
|
$recentChangesFlags[$key]['grouping'] : 'any' );
|
|
|
|
|
switch ( $flagGrouping ) {
|
|
|
|
|
case 'all':
|
|
|
|
|
if ( !$value ) {
|
|
|
|
|
$collectedRcFlags[$key] = false;
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
case 'any':
|
|
|
|
|
if ( $value ) {
|
|
|
|
|
$collectedRcFlags[$key] = true;
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
throw new DomainException( "Unknown grouping type \"{$flagGrouping}\"" );
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2015-10-19 08:33:54 +00:00
|
|
|
$lines[] = $line;
|
2015-09-16 10:44:04 +00:00
|
|
|
}
|
2016-05-04 14:47:03 +00:00
|
|
|
|
2015-09-16 10:44:04 +00:00
|
|
|
// Further down are some assumptions that $block is a 0-indexed array
|
|
|
|
|
// with (count-1) as last key. Let's make sure it is.
|
|
|
|
|
$block = array_values( $block );
|
2015-10-19 08:33:54 +00:00
|
|
|
|
|
|
|
|
if ( empty( $block ) || !$lines ) {
|
2015-09-23 11:24:34 +00:00
|
|
|
// if we can't show anything, don't display this block altogether
|
|
|
|
|
return '';
|
|
|
|
|
}
|
2015-09-16 10:44:04 +00:00
|
|
|
|
2015-10-19 08:33:54 +00:00
|
|
|
$logText = $this->getLogText( $block, $queryParams, $allLogs,
|
|
|
|
|
$collectedRcFlags['newpage'], $namehidden
|
|
|
|
|
);
|
2008-11-18 12:54:53 +00:00
|
|
|
|
2008-04-01 22:41:19 +00:00
|
|
|
# Character difference (does not apply if only log items)
|
2015-10-19 08:33:54 +00:00
|
|
|
$charDifference = false;
|
2014-08-22 20:01:08 +00:00
|
|
|
if ( $RCShowChangedSize && !$allLogs ) {
|
2008-04-01 22:41:19 +00:00
|
|
|
$last = 0;
|
2013-02-03 20:05:24 +00:00
|
|
|
$first = count( $block ) - 1;
|
2016-02-10 09:38:41 +00:00
|
|
|
# Some events (like logs and category changes) have an "empty" size, so we need to skip those...
|
2016-04-15 20:11:27 +00:00
|
|
|
while ( $last < $first && $block[$last]->mAttribs['rc_new_len'] === null ) {
|
2008-04-01 22:41:19 +00:00
|
|
|
$last++;
|
|
|
|
|
}
|
2016-04-15 20:11:27 +00:00
|
|
|
while ( $last < $first && $block[$first]->mAttribs['rc_old_len'] === null ) {
|
2008-04-01 22:41:19 +00:00
|
|
|
$first--;
|
|
|
|
|
}
|
|
|
|
|
# Get net change
|
2015-10-19 08:33:54 +00:00
|
|
|
$charDifference = $this->formatCharacterDifference( $block[$first], $block[$last] );
|
2015-09-16 10:44:04 +00:00
|
|
|
}
|
2015-06-25 19:13:23 +00:00
|
|
|
|
2015-10-19 08:33:54 +00:00
|
|
|
$numberofWatchingusers = $this->numberofWatchingusers( $block[0]->numberofWatchingusers );
|
|
|
|
|
$usersList = $this->msg( 'brackets' )->rawParams(
|
|
|
|
|
implode( $this->message['semicolon-separator'], $users )
|
|
|
|
|
)->escaped();
|
|
|
|
|
|
2016-02-17 09:09:32 +00:00
|
|
|
$templateParams = [
|
2015-10-19 08:33:54 +00:00
|
|
|
'articleLink' => $articleLink,
|
|
|
|
|
'charDifference' => $charDifference,
|
|
|
|
|
'collectedRcFlags' => $this->recentChangesFlags( $collectedRcFlags ),
|
|
|
|
|
'languageDirMark' => $this->getLanguage()->getDirMark(),
|
|
|
|
|
'lines' => $lines,
|
|
|
|
|
'logText' => $logText,
|
|
|
|
|
'numberofWatchingusers' => $numberofWatchingusers,
|
|
|
|
|
'rev-deleted-event' => $revDeletedMsg,
|
|
|
|
|
'tableClasses' => $tableClasses,
|
|
|
|
|
'timestamp' => $block[0]->timestamp,
|
|
|
|
|
'users' => $usersList,
|
2016-02-17 09:09:32 +00:00
|
|
|
];
|
2015-06-25 19:13:23 +00:00
|
|
|
|
2015-09-16 10:44:04 +00:00
|
|
|
$this->rcCacheIndex++;
|
2015-07-08 14:39:05 +00:00
|
|
|
|
2017-05-16 22:43:35 +00:00
|
|
|
return $this->templateParser->processTemplate(
|
2015-10-19 08:33:54 +00:00
|
|
|
'EnhancedChangesListGroup',
|
|
|
|
|
$templateParams
|
|
|
|
|
);
|
2015-09-16 10:44:04 +00:00
|
|
|
}
|
2015-06-25 19:13:23 +00:00
|
|
|
|
2015-09-16 10:44:04 +00:00
|
|
|
/**
|
|
|
|
|
* @param RCCacheEntry[] $block
|
|
|
|
|
* @param RCCacheEntry $rcObj
|
|
|
|
|
* @param array $queryParams
|
2015-10-19 08:33:54 +00:00
|
|
|
* @return array
|
2015-09-16 10:44:04 +00:00
|
|
|
* @throws Exception
|
|
|
|
|
* @throws FatalError
|
|
|
|
|
* @throws MWException
|
|
|
|
|
*/
|
2016-02-17 09:09:32 +00:00
|
|
|
protected function getLineData( array $block, RCCacheEntry $rcObj, array $queryParams = [] ) {
|
2015-09-16 10:44:04 +00:00
|
|
|
$RCShowChangedSize = $this->getConfig()->get( 'RCShowChangedSize' );
|
2015-06-25 19:13:23 +00:00
|
|
|
|
2015-09-16 10:44:04 +00:00
|
|
|
$type = $rcObj->mAttribs['rc_type'];
|
2016-02-17 09:09:32 +00:00
|
|
|
$data = [];
|
|
|
|
|
$lineParams = [];
|
2015-06-25 19:13:23 +00:00
|
|
|
|
2017-02-10 14:18:02 +00:00
|
|
|
$classes = [ 'mw-enhanced-rc' ];
|
2015-10-19 08:33:54 +00:00
|
|
|
if ( $rcObj->watched
|
|
|
|
|
&& $rcObj->mAttribs['rc_timestamp'] >= $rcObj->watched
|
|
|
|
|
) {
|
2017-02-28 19:21:19 +00:00
|
|
|
$classes[] = 'mw-enhanced-watched';
|
2015-10-19 08:33:54 +00:00
|
|
|
}
|
2017-02-10 14:18:02 +00:00
|
|
|
$classes = array_merge( $classes, $this->getHTMLClassesForFilters( $rcObj ) );
|
2016-03-28 04:58:11 +00:00
|
|
|
|
2015-09-16 10:44:04 +00:00
|
|
|
$separator = ' <span class="mw-changeslist-separator">. .</span> ';
|
2008-03-16 18:46:09 +00:00
|
|
|
|
2016-02-17 09:09:32 +00:00
|
|
|
$data['recentChangesFlags'] = [
|
2015-09-16 10:44:04 +00:00
|
|
|
'newpage' => $type == RC_NEW,
|
|
|
|
|
'minor' => $rcObj->mAttribs['rc_minor'],
|
|
|
|
|
'unpatrolled' => $rcObj->unpatrolled,
|
|
|
|
|
'bot' => $rcObj->mAttribs['rc_bot'],
|
2016-02-17 09:09:32 +00:00
|
|
|
];
|
2015-07-08 14:39:05 +00:00
|
|
|
|
2015-09-16 10:44:04 +00:00
|
|
|
$params = $queryParams;
|
2005-09-06 18:43:45 +00:00
|
|
|
|
2015-09-16 10:44:04 +00:00
|
|
|
if ( $rcObj->mAttribs['rc_this_oldid'] != 0 ) {
|
|
|
|
|
$params['oldid'] = $rcObj->mAttribs['rc_this_oldid'];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
# Log timestamp
|
|
|
|
|
if ( $type == RC_LOG ) {
|
|
|
|
|
$link = $rcObj->timestamp;
|
|
|
|
|
# Revision link
|
|
|
|
|
} elseif ( !ChangesList::userCan( $rcObj, Revision::DELETED_TEXT, $this->getUser() ) ) {
|
|
|
|
|
$link = '<span class="history-deleted">' . $rcObj->timestamp . '</span> ';
|
|
|
|
|
} else {
|
2016-05-13 07:24:29 +00:00
|
|
|
$link = $this->linkRenderer->makeKnownLink(
|
2015-09-16 10:44:04 +00:00
|
|
|
$rcObj->getTitle(),
|
2016-05-13 07:24:29 +00:00
|
|
|
new HtmlArmor( $rcObj->timestamp ),
|
2016-02-17 09:09:32 +00:00
|
|
|
[],
|
2015-09-16 10:44:04 +00:00
|
|
|
$params
|
|
|
|
|
);
|
|
|
|
|
if ( $this->isDeleted( $rcObj, Revision::DELETED_TEXT ) ) {
|
|
|
|
|
$link = '<span class="history-deleted">' . $link . '</span> ';
|
2015-09-16 09:56:29 +00:00
|
|
|
}
|
2015-09-16 10:44:04 +00:00
|
|
|
}
|
|
|
|
|
$data['timestampLink'] = $link;
|
2009-02-20 13:00:58 +00:00
|
|
|
|
2015-09-16 10:44:04 +00:00
|
|
|
$currentAndLastLinks = '';
|
|
|
|
|
if ( !$type == RC_LOG || $type == RC_NEW ) {
|
|
|
|
|
$currentAndLastLinks .= ' ' . $this->msg( 'parentheses' )->rawParams(
|
|
|
|
|
$rcObj->curlink .
|
|
|
|
|
$this->message['pipe-separator'] .
|
|
|
|
|
$rcObj->lastlink
|
|
|
|
|
)->escaped();
|
|
|
|
|
}
|
|
|
|
|
$data['currentAndLastLinks'] = $currentAndLastLinks;
|
|
|
|
|
$data['separatorAfterCurrentAndLastLinks'] = $separator;
|
|
|
|
|
|
|
|
|
|
# Character diff
|
|
|
|
|
if ( $RCShowChangedSize ) {
|
|
|
|
|
$cd = $this->formatCharacterDifference( $rcObj );
|
|
|
|
|
if ( $cd !== '' ) {
|
|
|
|
|
$data['characterDiff'] = $cd;
|
|
|
|
|
$data['separatorAfterCharacterDiff'] = $separator;
|
2015-09-16 09:56:29 +00:00
|
|
|
}
|
2015-09-16 10:44:04 +00:00
|
|
|
}
|
2015-07-08 14:39:05 +00:00
|
|
|
|
2015-09-16 10:44:04 +00:00
|
|
|
if ( $rcObj->mAttribs['rc_type'] == RC_LOG ) {
|
|
|
|
|
$data['logEntry'] = $this->insertLogEntry( $rcObj );
|
2015-08-24 17:40:06 +00:00
|
|
|
} elseif ( $this->isCategorizationWithoutRevision( $rcObj ) ) {
|
|
|
|
|
$data['comment'] = $this->insertComment( $rcObj );
|
2015-09-16 10:44:04 +00:00
|
|
|
} else {
|
|
|
|
|
# User links
|
|
|
|
|
$data['userLink'] = $rcObj->userlink;
|
|
|
|
|
$data['userTalkLink'] = $rcObj->usertalklink;
|
|
|
|
|
$data['comment'] = $this->insertComment( $rcObj );
|
|
|
|
|
}
|
2015-07-08 14:39:05 +00:00
|
|
|
|
2015-09-16 10:44:04 +00:00
|
|
|
# Rollback
|
|
|
|
|
$data['rollback'] = $this->getRollback( $rcObj );
|
2015-07-08 14:39:05 +00:00
|
|
|
|
2015-09-16 10:44:04 +00:00
|
|
|
# Tags
|
|
|
|
|
$data['tags'] = $this->getTags( $rcObj, $classes );
|
|
|
|
|
|
2017-02-10 05:31:32 +00:00
|
|
|
$attribs = $this->getDataAttributes( $rcObj );
|
|
|
|
|
|
2015-09-16 10:44:04 +00:00
|
|
|
// give the hook a chance to modify the data
|
|
|
|
|
$success = Hooks::run( 'EnhancedChangesListModifyLineData',
|
2017-02-10 05:31:32 +00:00
|
|
|
[ $this, &$data, $block, $rcObj, &$classes, &$attribs ] );
|
2015-09-16 10:44:04 +00:00
|
|
|
if ( !$success ) {
|
|
|
|
|
// skip entry if hook aborted it
|
2016-02-17 09:09:32 +00:00
|
|
|
return [];
|
2015-09-16 09:56:29 +00:00
|
|
|
}
|
2017-02-10 05:31:32 +00:00
|
|
|
$attribs = wfArrayFilterByKey( $attribs, [ Sanitizer::class, 'isReservedDataAttribute' ] );
|
2015-09-16 09:56:29 +00:00
|
|
|
|
2016-03-23 15:25:44 +00:00
|
|
|
$lineParams['recentChangesFlagsRaw'] = [];
|
2015-09-16 10:44:04 +00:00
|
|
|
if ( isset( $data['recentChangesFlags'] ) ) {
|
2015-10-19 08:33:54 +00:00
|
|
|
$lineParams['recentChangesFlags'] = $this->recentChangesFlags( $data['recentChangesFlags'] );
|
2016-03-23 15:25:44 +00:00
|
|
|
# FIXME: This is used by logic, don't return it in the template params.
|
|
|
|
|
$lineParams['recentChangesFlagsRaw'] = $data['recentChangesFlags'];
|
2015-09-16 10:44:04 +00:00
|
|
|
unset( $data['recentChangesFlags'] );
|
|
|
|
|
}
|
2015-09-16 09:56:29 +00:00
|
|
|
|
2015-09-16 10:44:04 +00:00
|
|
|
if ( isset( $data['timestampLink'] ) ) {
|
2015-10-19 08:33:54 +00:00
|
|
|
$lineParams['timestampLink'] = $data['timestampLink'];
|
2015-09-16 10:44:04 +00:00
|
|
|
unset( $data['timestampLink'] );
|
|
|
|
|
}
|
|
|
|
|
|
2016-07-08 09:36:09 +00:00
|
|
|
$lineParams['classes'] = array_values( $classes );
|
2017-02-10 05:31:32 +00:00
|
|
|
$lineParams['attribs'] = Html::expandAttributes( $attribs );
|
2016-07-08 09:36:09 +00:00
|
|
|
|
2015-09-16 10:44:04 +00:00
|
|
|
// everything else: makes it easier for extensions to add or remove data
|
2015-10-19 08:33:54 +00:00
|
|
|
$lineParams['data'] = array_values( $data );
|
2015-09-16 10:44:04 +00:00
|
|
|
|
2015-10-19 08:33:54 +00:00
|
|
|
return $lineParams;
|
2005-09-06 22:16:41 +00:00
|
|
|
}
|
2006-01-07 13:31:29 +00:00
|
|
|
|
2015-02-26 13:10:22 +00:00
|
|
|
/**
|
|
|
|
|
* Generates amount of changes (linking to diff ) & link to history.
|
|
|
|
|
*
|
|
|
|
|
* @param array $block
|
|
|
|
|
* @param array $queryParams
|
|
|
|
|
* @param bool $allLogs
|
|
|
|
|
* @param bool $isnew
|
|
|
|
|
* @param bool $namehidden
|
|
|
|
|
* @return string
|
|
|
|
|
*/
|
|
|
|
|
protected function getLogText( $block, $queryParams, $allLogs, $isnew, $namehidden ) {
|
2015-09-23 11:24:34 +00:00
|
|
|
if ( empty( $block ) ) {
|
|
|
|
|
return '';
|
|
|
|
|
}
|
|
|
|
|
|
2015-02-26 13:10:22 +00:00
|
|
|
# Changes message
|
2016-02-17 09:09:32 +00:00
|
|
|
static $nchanges = [];
|
|
|
|
|
static $sinceLastVisitMsg = [];
|
2015-02-26 13:10:22 +00:00
|
|
|
|
|
|
|
|
$n = count( $block );
|
|
|
|
|
if ( !isset( $nchanges[$n] ) ) {
|
|
|
|
|
$nchanges[$n] = $this->msg( 'nchanges' )->numParams( $n )->escaped();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
$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 ) {
|
|
|
|
|
$sinceLast++;
|
|
|
|
|
$unvisitedOldid = $rcObj->mAttribs['rc_last_oldid'];
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if ( !isset( $sinceLastVisitMsg[$sinceLast] ) ) {
|
|
|
|
|
$sinceLastVisitMsg[$sinceLast] =
|
|
|
|
|
$this->msg( 'enhancedrc-since-last-visit' )->numParams( $sinceLast )->escaped();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
$currentRevision = 0;
|
|
|
|
|
foreach ( $block as $rcObj ) {
|
|
|
|
|
if ( !$currentRevision ) {
|
|
|
|
|
$currentRevision = $rcObj->mAttribs['rc_this_oldid'];
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
# Total change link
|
2016-02-17 09:09:32 +00:00
|
|
|
$links = [];
|
2015-02-26 13:10:22 +00:00
|
|
|
/** @var $block0 RecentChange */
|
|
|
|
|
$block0 = $block[0];
|
|
|
|
|
$last = $block[count( $block ) - 1];
|
2016-03-10 16:48:59 +00:00
|
|
|
if ( !$allLogs ) {
|
|
|
|
|
if ( !ChangesList::userCan( $rcObj, Revision::DELETED_TEXT, $this->getUser() ) ||
|
|
|
|
|
$isnew ||
|
|
|
|
|
$rcObj->mAttribs['rc_type'] == RC_CATEGORIZE
|
|
|
|
|
) {
|
2015-02-26 13:10:22 +00:00
|
|
|
$links['total-changes'] = $nchanges[$n];
|
|
|
|
|
} else {
|
2016-05-13 07:24:29 +00:00
|
|
|
$links['total-changes'] = $this->linkRenderer->makeKnownLink(
|
2015-02-26 13:10:22 +00:00
|
|
|
$block0->getTitle(),
|
2016-05-13 07:24:29 +00:00
|
|
|
new HtmlArmor( $nchanges[$n] ),
|
2017-02-21 02:25:39 +00:00
|
|
|
[ 'class' => 'mw-changeslist-groupdiff' ],
|
2016-02-17 09:09:32 +00:00
|
|
|
$queryParams + [
|
2015-02-26 13:10:22 +00:00
|
|
|
'diff' => $currentRevision,
|
|
|
|
|
'oldid' => $last->mAttribs['rc_last_oldid'],
|
2016-05-13 07:24:29 +00:00
|
|
|
]
|
2015-02-26 13:10:22 +00:00
|
|
|
);
|
|
|
|
|
if ( $sinceLast > 0 && $sinceLast < $n ) {
|
2016-05-13 07:24:29 +00:00
|
|
|
$links['total-changes-since-last'] = $this->linkRenderer->makeKnownLink(
|
2015-02-26 13:10:22 +00:00
|
|
|
$block0->getTitle(),
|
2016-05-13 07:24:29 +00:00
|
|
|
new HtmlArmor( $sinceLastVisitMsg[$sinceLast] ),
|
2017-02-21 02:25:39 +00:00
|
|
|
[ 'class' => 'mw-changeslist-groupdiff' ],
|
2016-02-17 09:09:32 +00:00
|
|
|
$queryParams + [
|
2015-02-26 13:10:22 +00:00
|
|
|
'diff' => $currentRevision,
|
|
|
|
|
'oldid' => $unvisitedOldid,
|
2016-05-13 07:24:29 +00:00
|
|
|
]
|
2015-02-26 13:10:22 +00:00
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
# History
|
2015-08-24 17:40:06 +00:00
|
|
|
if ( $allLogs || $rcObj->mAttribs['rc_type'] == RC_CATEGORIZE ) {
|
2015-02-26 13:10:22 +00:00
|
|
|
// don't show history link for logs
|
|
|
|
|
} elseif ( $namehidden || !$block0->getTitle()->exists() ) {
|
|
|
|
|
$links['history'] = $this->message['enhancedrc-history'];
|
|
|
|
|
} else {
|
|
|
|
|
$params = $queryParams;
|
|
|
|
|
$params['action'] = 'history';
|
|
|
|
|
|
2016-05-13 07:24:29 +00:00
|
|
|
$links['history'] = $this->linkRenderer->makeKnownLink(
|
2015-02-26 13:10:22 +00:00
|
|
|
$block0->getTitle(),
|
2016-05-13 07:24:29 +00:00
|
|
|
new HtmlArmor( $this->message['enhancedrc-history'] ),
|
2017-02-21 02:25:39 +00:00
|
|
|
[ 'class' => 'mw-changeslist-history' ],
|
2015-02-26 13:10:22 +00:00
|
|
|
$params
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
# Allow others to alter, remove or add to these links
|
|
|
|
|
Hooks::run( 'EnhancedChangesList::getLogText',
|
2016-02-17 09:09:32 +00:00
|
|
|
[ $this, &$links, $block ] );
|
2015-02-26 13:10:22 +00:00
|
|
|
|
|
|
|
|
if ( !$links ) {
|
|
|
|
|
return '';
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
$logtext = implode( $this->message['pipe-separator'], $links );
|
|
|
|
|
$logtext = $this->msg( 'parentheses' )->rawParams( $logtext )->escaped();
|
|
|
|
|
return ' ' . $logtext;
|
|
|
|
|
}
|
|
|
|
|
|
2005-12-16 23:56:44 +00:00
|
|
|
/**
|
|
|
|
|
* Enhanced RC ungrouped line.
|
2011-04-04 21:23:22 +00:00
|
|
|
*
|
2013-11-19 12:25:54 +00:00
|
|
|
* @param RecentChange|RCCacheEntry $rcObj
|
|
|
|
|
* @return string A HTML formatted line (generated using $r)
|
2005-12-16 23:56:44 +00:00
|
|
|
*/
|
2008-04-04 13:16:58 +00:00
|
|
|
protected function recentChangesBlockLine( $rcObj ) {
|
2016-02-17 09:09:32 +00:00
|
|
|
$data = [];
|
2015-07-02 12:09:41 +00:00
|
|
|
|
2010-12-27 19:07:28 +00:00
|
|
|
$query['curid'] = $rcObj->mAttribs['rc_cur_id'];
|
2009-02-20 13:00:58 +00:00
|
|
|
|
2010-12-27 19:07:28 +00:00
|
|
|
$type = $rcObj->mAttribs['rc_type'];
|
|
|
|
|
$logType = $rcObj->mAttribs['rc_log_type'];
|
2015-09-28 16:01:10 +00:00
|
|
|
$classes = $this->getHTMLClasses( $rcObj, $rcObj->watched );
|
|
|
|
|
$classes[] = 'mw-enhanced-rc';
|
|
|
|
|
|
2013-04-20 22:49:30 +00:00
|
|
|
if ( $logType ) {
|
2010-11-08 21:21:32 +00:00
|
|
|
# Log entry
|
2014-01-14 06:19:21 +00:00
|
|
|
$classes[] = Sanitizer::escapeClass( 'mw-changeslist-log-' . $logType );
|
2010-11-08 21:21:32 +00:00
|
|
|
} else {
|
2012-05-12 03:33:04 +00:00
|
|
|
$classes[] = Sanitizer::escapeClass( 'mw-changeslist-ns' .
|
2013-11-18 22:07:49 +00:00
|
|
|
$rcObj->mAttribs['rc_namespace'] . '-' . $rcObj->mAttribs['rc_title'] );
|
2010-11-08 21:21:32 +00:00
|
|
|
}
|
|
|
|
|
|
2005-12-16 23:56:44 +00:00
|
|
|
# Flag and Timestamp
|
2016-02-17 09:09:32 +00:00
|
|
|
$data['recentChangesFlags'] = [
|
2014-06-05 00:54:02 +00:00
|
|
|
'newpage' => $type == RC_NEW,
|
|
|
|
|
'minor' => $rcObj->mAttribs['rc_minor'],
|
|
|
|
|
'unpatrolled' => $rcObj->unpatrolled,
|
|
|
|
|
'bot' => $rcObj->mAttribs['rc_bot'],
|
2016-02-17 09:09:32 +00:00
|
|
|
];
|
2015-07-02 12:09:41 +00:00
|
|
|
// timestamp is not really a link here, but is called timestampLink
|
|
|
|
|
// for consistency with EnhancedChangesListModifyLineData
|
|
|
|
|
$data['timestampLink'] = $rcObj->timestamp;
|
|
|
|
|
|
2008-04-04 03:56:48 +00:00
|
|
|
# Article or log link
|
2013-04-20 22:49:30 +00:00
|
|
|
if ( $logType ) {
|
2012-06-18 22:56:55 +00:00
|
|
|
$logPage = new LogPage( $logType );
|
|
|
|
|
$logTitle = SpecialPage::getTitleFor( 'Log', $logType );
|
2016-05-13 07:24:29 +00:00
|
|
|
$logName = $logPage->getName()->text();
|
2015-07-02 12:09:41 +00:00
|
|
|
$data['logLink'] = $this->msg( 'parentheses' )
|
2016-05-13 07:24:29 +00:00
|
|
|
->rawParams(
|
|
|
|
|
$this->linkRenderer->makeKnownLink( $logTitle, $logName )
|
|
|
|
|
)->escaped();
|
2008-03-16 18:46:09 +00:00
|
|
|
} else {
|
2015-07-02 12:09:41 +00:00
|
|
|
$data['articleLink'] = $this->getArticleLink( $rcObj, $rcObj->unpatrolled, $rcObj->watched );
|
2008-03-16 18:46:09 +00:00
|
|
|
}
|
2015-07-02 12:09:41 +00:00
|
|
|
|
2008-04-04 03:56:48 +00:00
|
|
|
# Diff and hist links
|
2015-10-28 20:48:46 +00:00
|
|
|
if ( $type != RC_LOG && $type != RC_CATEGORIZE ) {
|
2009-06-06 22:42:48 +00:00
|
|
|
$query['action'] = 'history';
|
2015-08-24 17:40:06 +00:00
|
|
|
$data['historyLink'] = $this->getDiffHistLinks( $rcObj, $query );
|
2008-03-16 18:46:09 +00:00
|
|
|
}
|
2015-07-02 12:09:41 +00:00
|
|
|
$data['separatorAfterLinks'] = ' <span class="mw-changeslist-separator">. .</span> ';
|
|
|
|
|
|
2006-12-13 20:08:02 +00:00
|
|
|
# Character diff
|
2014-08-22 20:01:08 +00:00
|
|
|
if ( $this->getConfig()->get( 'RCShowChangedSize' ) ) {
|
2012-06-28 09:31:55 +00:00
|
|
|
$cd = $this->formatCharacterDifference( $rcObj );
|
|
|
|
|
if ( $cd !== '' ) {
|
2015-07-02 12:09:41 +00:00
|
|
|
$data['characterDiff'] = $cd;
|
|
|
|
|
$data['separatorAftercharacterDiff'] = ' <span class="mw-changeslist-separator">. .</span> ';
|
2012-06-28 09:31:55 +00:00
|
|
|
}
|
2006-12-13 20:08:02 +00:00
|
|
|
}
|
2011-09-08 09:15:59 +00:00
|
|
|
|
|
|
|
|
if ( $type == RC_LOG ) {
|
2015-07-02 12:09:41 +00:00
|
|
|
$data['logEntry'] = $this->insertLogEntry( $rcObj );
|
2015-08-24 17:40:06 +00:00
|
|
|
} elseif ( $this->isCategorizationWithoutRevision( $rcObj ) ) {
|
|
|
|
|
$data['comment'] = $this->insertComment( $rcObj );
|
2012-06-28 09:31:55 +00:00
|
|
|
} else {
|
2015-07-02 12:09:41 +00:00
|
|
|
$data['userLink'] = $rcObj->userlink;
|
|
|
|
|
$data['userTalkLink'] = $rcObj->usertalklink;
|
|
|
|
|
$data['comment'] = $this->insertComment( $rcObj );
|
2015-08-24 17:40:06 +00:00
|
|
|
if ( $type == RC_CATEGORIZE ) {
|
|
|
|
|
$data['historyLink'] = $this->getDiffHistLinks( $rcObj, $query );
|
|
|
|
|
}
|
2015-07-02 12:09:41 +00:00
|
|
|
$data['rollback'] = $this->getRollback( $rcObj );
|
2008-04-04 03:56:48 +00:00
|
|
|
}
|
2011-09-08 09:15:59 +00:00
|
|
|
|
2009-02-18 04:39:52 +00:00
|
|
|
# Tags
|
2015-07-02 12:09:41 +00:00
|
|
|
$data['tags'] = $this->getTags( $rcObj, $classes );
|
|
|
|
|
|
2008-04-04 03:56:48 +00:00
|
|
|
# Show how many people are watching this if enabled
|
2015-07-02 12:09:41 +00:00
|
|
|
$data['watchingUsers'] = $this->numberofWatchingusers( $rcObj->numberofWatchingusers );
|
2005-12-16 23:56:44 +00:00
|
|
|
|
2017-02-10 05:31:32 +00:00
|
|
|
$data['attribs'] = array_merge( $this->getDataAttributes( $rcObj ), [ 'class' => $classes ] );
|
|
|
|
|
|
2015-07-02 12:09:41 +00:00
|
|
|
// give the hook a chance to modify the data
|
2015-07-02 12:32:50 +00:00
|
|
|
$success = Hooks::run( 'EnhancedChangesListModifyBlockLineData',
|
2016-02-17 09:09:32 +00:00
|
|
|
[ $this, &$data, $rcObj ] );
|
2015-07-02 12:32:50 +00:00
|
|
|
if ( !$success ) {
|
|
|
|
|
// skip entry if hook aborted it
|
|
|
|
|
return '';
|
|
|
|
|
}
|
2017-02-10 05:31:32 +00:00
|
|
|
$attribs = $data['attribs'];
|
|
|
|
|
unset( $data['attribs'] );
|
2017-06-26 16:35:31 +00:00
|
|
|
$attribs = wfArrayFilterByKey( $attribs, function ( $key ) {
|
2017-06-14 21:01:31 +00:00
|
|
|
return $key === 'class' || Sanitizer::isReservedDataAttribute( $key );
|
|
|
|
|
} );
|
2009-02-20 13:00:58 +00:00
|
|
|
|
2017-02-10 05:31:32 +00:00
|
|
|
$line = Html::openElement( 'table', $attribs ) . Html::openElement( 'tr' );
|
2015-07-02 12:09:41 +00:00
|
|
|
$line .= '<td class="mw-enhanced-rc"><span class="mw-enhancedchanges-arrow-space"></span>';
|
|
|
|
|
|
|
|
|
|
if ( isset( $data['recentChangesFlags'] ) ) {
|
|
|
|
|
$line .= $this->recentChangesFlags( $data['recentChangesFlags'] );
|
|
|
|
|
unset( $data['recentChangesFlags'] );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if ( isset( $data['timestampLink'] ) ) {
|
|
|
|
|
$line .= ' ' . $data['timestampLink'];
|
|
|
|
|
unset( $data['timestampLink'] );
|
|
|
|
|
}
|
|
|
|
|
$line .= ' </td><td>';
|
|
|
|
|
|
|
|
|
|
// everything else: makes it easier for extensions to add or remove data
|
|
|
|
|
$line .= implode( '', $data );
|
|
|
|
|
|
|
|
|
|
$line .= "</td></tr></table>\n";
|
|
|
|
|
|
|
|
|
|
return $line;
|
2005-12-16 23:56:44 +00:00
|
|
|
}
|
|
|
|
|
|
2015-08-24 17:40:06 +00:00
|
|
|
/**
|
|
|
|
|
* Returns value to be used in 'historyLink' element of $data param in
|
|
|
|
|
* EnhancedChangesListModifyBlockLineData hook.
|
|
|
|
|
*
|
|
|
|
|
* @since 1.27
|
|
|
|
|
*
|
|
|
|
|
* @param RCCacheEntry $rc
|
|
|
|
|
* @param array $query array of key/value pairs to append as a query string
|
|
|
|
|
* @return string HTML
|
|
|
|
|
*/
|
|
|
|
|
public function getDiffHistLinks( RCCacheEntry $rc, array $query ) {
|
|
|
|
|
$pageTitle = $rc->getTitle();
|
|
|
|
|
if ( $rc->getAttribute( 'rc_type' ) == RC_CATEGORIZE ) {
|
|
|
|
|
// For categorizations we must swap the category title with the page title!
|
|
|
|
|
$pageTitle = Title::newFromID( $rc->getAttribute( 'rc_cur_id' ) );
|
2017-05-19 22:08:14 +00:00
|
|
|
if ( !$pageTitle ) {
|
|
|
|
|
// The page has been deleted, but the RC entry
|
|
|
|
|
// deletion job has not run yet. Just skip.
|
|
|
|
|
return '';
|
|
|
|
|
}
|
2015-08-24 17:40:06 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
$retVal = ' ' . $this->msg( 'parentheses' )
|
2016-05-13 07:24:29 +00:00
|
|
|
->rawParams( $rc->difflink . $this->message['pipe-separator']
|
|
|
|
|
. $this->linkRenderer->makeKnownLink(
|
2015-08-24 17:40:06 +00:00
|
|
|
$pageTitle,
|
2016-05-13 07:24:29 +00:00
|
|
|
new HtmlArmor( $this->message['hist'] ),
|
2017-02-21 02:25:39 +00:00
|
|
|
[ 'class' => 'mw-changeslist-history' ],
|
2015-08-24 17:40:06 +00:00
|
|
|
$query
|
|
|
|
|
) )->escaped();
|
|
|
|
|
return $retVal;
|
|
|
|
|
}
|
|
|
|
|
|
2005-12-16 23:56:44 +00:00
|
|
|
/**
|
|
|
|
|
* If enhanced RC is in use, this function takes the previously cached
|
|
|
|
|
* RC lines, arranges them, and outputs the HTML
|
2011-05-20 22:03:10 +00:00
|
|
|
*
|
|
|
|
|
* @return string
|
2005-12-16 23:56:44 +00:00
|
|
|
*/
|
2008-04-04 13:16:58 +00:00
|
|
|
protected function recentChangesBlock() {
|
2013-11-18 22:07:49 +00:00
|
|
|
if ( count( $this->rc_cache ) == 0 ) {
|
2005-12-16 23:56:44 +00:00
|
|
|
return '';
|
|
|
|
|
}
|
2009-02-20 13:00:58 +00:00
|
|
|
|
2005-12-16 23:56:44 +00:00
|
|
|
$blockOut = '';
|
2013-04-20 22:49:30 +00:00
|
|
|
foreach ( $this->rc_cache as $block ) {
|
|
|
|
|
if ( count( $block ) < 2 ) {
|
2005-12-16 23:56:44 +00:00
|
|
|
$blockOut .= $this->recentChangesBlockLine( array_shift( $block ) );
|
|
|
|
|
} else {
|
|
|
|
|
$blockOut .= $this->recentChangesBlockGroup( $block );
|
|
|
|
|
}
|
|
|
|
|
}
|
2009-02-20 13:00:58 +00:00
|
|
|
|
2017-07-20 18:38:52 +00:00
|
|
|
if ( $blockOut === '' ) {
|
|
|
|
|
return '';
|
|
|
|
|
}
|
|
|
|
|
// $this->lastdate is kept up to date by recentChangesLine()
|
|
|
|
|
return Xml::element( 'h4', null, $this->lastdate ) . "\n<div>" . $blockOut . '</div>';
|
2005-12-16 23:56:44 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
2011-05-25 15:39:47 +00:00
|
|
|
* Returns text for the end of RC
|
2005-12-16 23:56:44 +00:00
|
|
|
* If enhanced RC is in use, returns pretty much all the text
|
2012-01-12 19:03:32 +00:00
|
|
|
* @return string
|
2005-12-16 23:56:44 +00:00
|
|
|
*/
|
2008-04-04 05:08:25 +00:00
|
|
|
public function endRecentChangesList() {
|
2013-11-26 22:13:51 +00:00
|
|
|
return $this->recentChangesBlock() . '</div>';
|
2005-12-16 23:56:44 +00:00
|
|
|
}
|
2005-09-06 22:16:41 +00:00
|
|
|
}
|