gplx/mediawiki/extensions/ApprovedRevs/includes/specials/SpecialApprovedRevs.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';
}
}