357 lines
9.9 KiB
PHP
357 lines
9.9 KiB
PHP
<?php
|
|
|
|
use MediaWiki\MediaWikiServices;
|
|
|
|
/**
|
|
* Special page that displays various lists of pages that either do or do
|
|
* not have an approved revision.
|
|
*
|
|
* @author Yaron Koren
|
|
*/
|
|
class SpecialApprovedRevs extends QueryPage {
|
|
|
|
protected $mMode;
|
|
|
|
public function __construct() {
|
|
parent::__construct( 'ApprovedRevs' );
|
|
$request = $this->getRequest();
|
|
$this->mMode = $request->getVal( 'show' );
|
|
}
|
|
|
|
/**
|
|
* These two arrays pair mode with messages. E.g. mode "approvedpages"
|
|
* is used to generate a header link with query string having "show=approvedpages"
|
|
* and link text of "All pages with an approved revision" (in English).
|
|
*/
|
|
protected $mPageHeaderLinks = [
|
|
'approvedrevs-notlatestpages' => '',
|
|
'approvedrevs-unapprovedpages' => 'unapproved',
|
|
'approvedrevs-approvedpages' => 'all',
|
|
'approvedrevs-invalidpages' => 'invalid',
|
|
];
|
|
protected $mFileHeaderLinks = [
|
|
'approvedrevs-notlatestfiles' => 'notlatestfiles',
|
|
'approvedrevs-unapprovedfiles' => 'unapprovedfiles',
|
|
'approvedrevs-approvedfiles' => 'approvedfiles',
|
|
'approvedrevs-invalidfiles' => 'invalidfiles',
|
|
];
|
|
|
|
public function isExpensive() {
|
|
return false;
|
|
}
|
|
|
|
public function isSyndicated() {
|
|
return false;
|
|
}
|
|
|
|
protected function getPageHeader() {
|
|
global $egApprovedRevsEnabledNamespaces;
|
|
|
|
// Show the page approval links, with the one
|
|
// corresponding to the current "mode" not being linked.
|
|
$navLinks = [];
|
|
foreach ( $this->mPageHeaderLinks as $msg => $mode ) {
|
|
$navLinks[] = $this->createHeaderLink( $msg, $mode );
|
|
}
|
|
// Also add the file approval links, but only if there have
|
|
// been any file approvals.
|
|
if (
|
|
isset( $egApprovedRevsEnabledNamespaces[NS_FILE] )
|
|
&& $egApprovedRevsEnabledNamespaces[NS_FILE]
|
|
) {
|
|
$dbr = ApprovedRevs::getReadDB();
|
|
$result = $dbr->selectField( 'approved_revs_files', 'COUNT(*)' );
|
|
if ( $result > 0 ) {
|
|
foreach ( $this->mFileHeaderLinks as $msg => $mode ) {
|
|
$navLinks[] = $this->createHeaderLink( $msg, $mode );
|
|
}
|
|
}
|
|
}
|
|
|
|
$navLine = $this->msg( 'approvedrevs-view' )->escaped() . ' ' . implode( ' | ', $navLinks );
|
|
$header = Xml::tags( 'p', null, $navLine ) . "\n";
|
|
|
|
return Xml::tags(
|
|
'div', [ 'class' => 'specialapprovedrevs-header' ], $header
|
|
);
|
|
}
|
|
|
|
/**
|
|
* Generate links for header. For current mode, generate non-link bold
|
|
* text.
|
|
*/
|
|
public function createHeaderLink( $msg, $mode ) {
|
|
if ( $this->mMode == $mode ) {
|
|
return Html::element( 'strong',
|
|
null,
|
|
$this->msg( $msg )->text()
|
|
);
|
|
} else {
|
|
$approvedPagesTitle = SpecialPage::getTitleFor( $this->getName() );
|
|
$show = ( $mode == '' ) ? [] : [ 'show' => $mode ];
|
|
return Html::element( 'a',
|
|
[ 'href' => $approvedPagesTitle->getLocalURL( $show ) ],
|
|
$this->msg( $msg )->text()
|
|
);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Set parameters for standard navigation links.
|
|
* i.e. Applies mode to next/prev links when paging through list, etc.
|
|
*/
|
|
protected function linkParameters() {
|
|
// Optionally could validate $this->mMode against the two
|
|
// link arrays.
|
|
return $this->mMode == '' ? [] : [ 'show' => $this->mMode ];
|
|
}
|
|
|
|
public function getQueryInfo() {
|
|
// SQL for page revision approvals versus file revision approvals is
|
|
// significantly different. Easier to follow if broken into two functions.
|
|
if ( in_array(
|
|
$this->mMode,
|
|
[ 'notlatestfiles', 'unapprovedfiles', 'approvedfiles', 'invalidfiles' ]
|
|
) ) {
|
|
$query = ApprovedRevs::getQueryInfoFileApprovals( $this->mMode );
|
|
} else {
|
|
$query = ApprovedRevs::getQueryInfoPageApprovals( $this->mMode );
|
|
}
|
|
if ( in_array( $this->mMode, [ 'all', 'approvedfiles' ] ) ) {
|
|
$query['tables'] = array_merge( $query['tables'], [ 'logging', 'actor' ] );
|
|
$query['fields'] = array_merge( $query['fields'], [
|
|
'log_user' => 'actor_user',
|
|
'log_user_name' => 'actor_name',
|
|
'log_timestamp',
|
|
] );
|
|
$query['join_conds'] += [
|
|
'logging' => [ 'LEFT OUTER JOIN', 'p.page_id=log_page' ],
|
|
'actor' => [ 'JOIN', 'log_actor=actor_id' ],
|
|
];
|
|
$query['conds']['log_type'] = 'approval';
|
|
}
|
|
return $query;
|
|
}
|
|
|
|
protected function getOrderFields() {
|
|
return [ 'p.page_namespace', 'p.page_title' ];
|
|
}
|
|
|
|
protected function sortDescending() {
|
|
return false;
|
|
}
|
|
|
|
protected function formatResult( $skin, $result ) {
|
|
// SQL for page revision approvals versus file revision approvals is
|
|
// significantly different. Easier to follow if broken into two functions.
|
|
if ( in_array(
|
|
$this->mMode,
|
|
[ 'notlatestfiles', 'unapprovedfiles', 'approvedfiles', 'invalidfiles' ]
|
|
) ) {
|
|
return $this->formatResultFileApprovals( $skin, $result );
|
|
} else {
|
|
return $this->formatResultPageApprovals( $skin, $result );
|
|
}
|
|
}
|
|
|
|
public function formatResultPageApprovals( $skin, $result ) {
|
|
$title = Title::newFromId( $result->id );
|
|
if ( $title === null ) {
|
|
return false;
|
|
}
|
|
|
|
if ( !ApprovedRevs::pageIsApprovable( $title ) && $this->mMode !== 'invalid' ) {
|
|
return false;
|
|
}
|
|
|
|
$context = $skin->getContext();
|
|
$user = $context->getUser();
|
|
$lang = $context->getLanguage();
|
|
$linkRenderer = $this->getLinkRenderer();
|
|
|
|
// Create page link - special handling for redirects.
|
|
$params = [];
|
|
if ( $title->isRedirect() ) {
|
|
$params['redirect'] = 'no';
|
|
}
|
|
$pageLink = $linkRenderer->makeLink( $title, null, [], $params );
|
|
if ( $title->isRedirect() ) {
|
|
$pageLink = "<em>$pageLink</em>";
|
|
}
|
|
|
|
if ( $this->mMode == 'all' ) {
|
|
$additionalInfo = Xml::element( 'span',
|
|
[
|
|
'class' => $result->rev_id == $result->latest_id ? 'approvedRevIsLatest' : 'approvedRevNotLatest'
|
|
],
|
|
$this->msg( 'approvedrevs-revisionnumber', $result->rev_id )->text()
|
|
);
|
|
|
|
if ( isset( $result->log_timestamp ) ) {
|
|
$timestampInteger = wfTimestamp( TS_MW, $result->log_timestamp );
|
|
$timestamp = $lang->timeanddate( $timestampInteger, true );
|
|
$date = $lang->date( $timestampInteger, true );
|
|
$time = $lang->time( $timestampInteger, true );
|
|
$userLink = Linker::userLink( $result->log_user, $result->log_user_name );
|
|
$additionalInfo .= ', ' . $this->msg( 'approvedrevs-approvedby' )
|
|
->rawParams( $userLink )
|
|
->params(
|
|
$timestamp,
|
|
$result->log_user_name,
|
|
$date,
|
|
$time
|
|
)
|
|
->escaped();
|
|
}
|
|
|
|
return "$pageLink ($additionalInfo)";
|
|
} elseif ( $this->mMode == 'unapproved' ) {
|
|
global $egApprovedRevsShowApproveLatest;
|
|
|
|
$line = $pageLink;
|
|
if ( $egApprovedRevsShowApproveLatest &&
|
|
ApprovedRevs::checkPermission( $user, $title, 'approverevisions' ) ) {
|
|
$line .= ' (' . Xml::element( 'a',
|
|
[ 'href' => $title->getLocalUrl(
|
|
[
|
|
'action' => 'approve',
|
|
'oldid' => $result->latest_id
|
|
]
|
|
) ],
|
|
$this->msg( 'approvedrevs-approvelatest' )->text()
|
|
) . ')';
|
|
}
|
|
|
|
return $line;
|
|
} elseif ( $this->mMode == 'invalid' ) {
|
|
return $pageLink;
|
|
} else {
|
|
// approved revision is not latest
|
|
$diffLink = Xml::element( 'a',
|
|
[ 'href' => $title->getLocalUrl(
|
|
[
|
|
'diff' => $result->latest_id,
|
|
'oldid' => $result->rev_id
|
|
]
|
|
) ],
|
|
$this->msg( 'approvedrevs-difffromlatest' )->text()
|
|
);
|
|
|
|
return "$pageLink ($diffLink)";
|
|
}
|
|
}
|
|
|
|
public function formatResultFileApprovals( $skin, $result ) {
|
|
$title = Title::makeTitle( NS_FILE, $result->title );
|
|
|
|
$pageLink = $this->getLinkRenderer()->makeLink( $title );
|
|
|
|
#
|
|
# mode: unapprovedfiles
|
|
#
|
|
if ( $this->mMode == 'unapprovedfiles' ) {
|
|
global $egApprovedRevsShowApproveLatest;
|
|
|
|
if ( $egApprovedRevsShowApproveLatest && ApprovedRevs::userCanApprove( $this->getUser(), $title ) ) {
|
|
$approveLink = ' (' . Xml::element(
|
|
'a',
|
|
[
|
|
'href' => $title->getLocalUrl(
|
|
[
|
|
'action' => 'approvefile',
|
|
'ts' => $result->latest_ts,
|
|
'sha1' => $result->latest_sha1
|
|
]
|
|
)
|
|
],
|
|
$this->msg( 'approvedrevs-approve' )->text()
|
|
) . ')';
|
|
} else {
|
|
$approveLink = '';
|
|
}
|
|
|
|
return "$pageLink$approveLink";
|
|
|
|
#
|
|
# mode: invalidfiles
|
|
#
|
|
} elseif ( $this->mMode == 'invalidfiles' ) {
|
|
|
|
if ( !ApprovedRevs::fileIsApprovable( $title ) ) {
|
|
// if showing invalid files only, don't show files
|
|
// that have real approvability
|
|
return '';
|
|
}
|
|
|
|
return $pageLink;
|
|
|
|
#
|
|
# mode: approvedfiles
|
|
#
|
|
} elseif ( $this->mMode == 'approvedfiles' ) {
|
|
$additionalInfo = Html::rawElement( 'span',
|
|
[
|
|
'class' =>
|
|
( $result->approved_sha1 == $result->latest_sha1
|
|
&& $result->approved_ts == $result->latest_ts
|
|
) ? 'approvedRevIsLatest' : 'approvedRevNotLatest'
|
|
],
|
|
$this->msg(
|
|
'approvedrevs-uploaddate',
|
|
wfTimestamp( TS_RFC2822, $result->approved_ts )
|
|
)->parse()
|
|
);
|
|
|
|
if ( isset( $result->log_timestamp ) ) {
|
|
$lang = $this->getLanguage();
|
|
$timestampInteger = wfTimestamp( TS_MW, $result->log_timestamp );
|
|
$timestamp = $lang->timeanddate( $timestampInteger, true );
|
|
$date = $lang->date( $timestampInteger, true );
|
|
$time = $lang->time( $timestampInteger, true );
|
|
$userLink = Linker::userLink( $result->log_user, $result->log_user_name );
|
|
$additionalInfo .= ', ' . $this->msg( 'approvedrevs-approvedby' )
|
|
->rawParams( $userLink )
|
|
->params(
|
|
$timestamp,
|
|
$result->log_user_name,
|
|
$date,
|
|
$time
|
|
)
|
|
->escaped();
|
|
}
|
|
|
|
return "$pageLink ($additionalInfo)";
|
|
|
|
#
|
|
# mode: notlatestfiles
|
|
#
|
|
} elseif ( $this->mMode == 'notlatestfiles' ) {
|
|
$repoGroup = MediaWikiServices::getInstance()->getRepoGroup();
|
|
$approved_file = $repoGroup->findFileFromKey(
|
|
$result->approved_sha1,
|
|
[ 'time' => $result->approved_ts ]
|
|
);
|
|
$latest_file = $repoGroup->findFileFromKey(
|
|
$result->latest_sha1,
|
|
[ 'time' => $result->latest_ts ]
|
|
);
|
|
|
|
$approvedLink = Xml::element( 'a',
|
|
[ 'href' => $approved_file->getUrl() ],
|
|
$this->msg( 'approvedrevs-approvedfile' )->text()
|
|
);
|
|
$latestLink = Xml::element( 'a',
|
|
[ 'href' => $latest_file->getUrl() ],
|
|
$this->msg( 'approvedrevs-latestfile' )->text()
|
|
);
|
|
|
|
return "$pageLink ($approvedLink | $latestLink)";
|
|
}
|
|
}
|
|
|
|
protected function getGroupName() {
|
|
return 'pages';
|
|
}
|
|
|
|
}
|