59 private $formattedComments = [];
62 private $revisions = [];
68 private $revisionFactory;
71 private $commentFormatter;
74 private $linkBatchFactory;
98 parent::__construct( $context, $linkRenderer );
100 $msgs = [
'deletionlog',
'undeleteviewlink',
'diff' ];
101 foreach ( $msgs as $msg ) {
102 $this->messages[$msg] = $this->
msg( $msg )->text();
105 $this->
namespace = $namespace;
106 $this->hookRunner =
new HookRunner( $hookContainer );
107 $this->revisionFactory = $revisionFactory;
108 $this->commentFormatter = $commentFormatter;
109 $this->linkBatchFactory = $linkBatchFactory;
113 $query = parent::getDefaultQuery();
122 $conds = array_merge( $userCond, $this->getNamespaceCond() );
124 if ( !$this->
getAuthority()->isAllowed(
'deletedhistory' ) ) {
125 $conds[] =
$dbr->bitAnd(
'ar_deleted', RevisionRecord::DELETED_USER ) .
' = 0';
126 } elseif ( !$this->
getAuthority()->isAllowedAny(
'suppressrevision',
'viewsuppressed' ) ) {
127 $conds[] =
$dbr->bitAnd(
'ar_deleted', RevisionRecord::SUPPRESSED_USER ) .
128 ' != ' . RevisionRecord::SUPPRESSED_USER;
131 $queryInfo = $this->revisionFactory->getArchiveQueryInfo();
132 $queryInfo[
'conds'] = $conds;
133 $queryInfo[
'options'] = [];
136 $queryInfo[
'join_conds'] = $queryInfo[
'joins'];
137 unset( $queryInfo[
'joins'] );
140 $queryInfo[
'tables'],
141 $queryInfo[
'fields'],
143 $queryInfo[
'join_conds'],
144 $queryInfo[
'options'],
153 $this->mResult->seek( 0 );
155 $linkBatch = $this->linkBatchFactory->newLinkBatch();
158 foreach ( $this->mResult as $row ) {
159 if ( $this->revisionFactory->isRevisionRow( $row,
'archive' ) ) {
160 $revisionRows[] = $row;
161 $linkBatch->add( $row->ar_namespace, $row->ar_title );
166 $linkBatch->execute();
168 foreach ( $revisionRows as $row ) {
169 $revisions[$row->ar_rev_id] = $this->revisionFactory->newRevisionFromArchiveRow(
171 RevisionFactory::READ_NORMAL,
172 Title::makeTitle( $row->ar_namespace, $row->ar_title )
176 $this->formattedComments = $this->commentFormatter->createRevisionBatch()
178 ->revisions( $revisions )
185 $this->revisions += $revisions;
198 $data = [ parent::reallyDoQuery( $offset, $limit, $order ) ];
202 $this->hookRunner->onDeletedContribsPager__reallyDoQuery(
203 $data, $this, $offset, $limit, $order );
208 foreach ( $data as $query ) {
209 foreach ( $query as $i => $row ) {
216 if ( $order === self::QUERY_ASCENDING ) {
223 $result = array_slice( $result, 0, $limit );
226 $result = array_values( $result );
239 return 'ar_timestamp';
246 return $this->target;
253 return $this->namespace;
260 return "<section class='mw-pager-body'>\n";
267 return "</section>\n";
270 private function getNamespaceCond() {
271 if ( $this->
namespace !==
'' ) {
272 return [
'ar_namespace' => (int)$this->
namespace ];
290 if ( $this->revisionFactory->isRevisionRow( $row,
'archive' ) ) {
291 $attribs[
'data-mw-revid'] = $row->ar_rev_id;
292 [ $ret, $classes ] = $this->formatRevisionRow( $row );
296 $this->hookRunner->onDeletedContributionsLineEnding(
297 $this, $ret, $row, $classes, $attribs );
298 $attribs = array_filter( $attribs,
299 [ Sanitizer::class,
'isReservedDataAttribute' ],
303 if ( $classes === [] && $attribs === [] && $ret ===
'' ) {
304 wfDebug(
"Dropping Special:DeletedContribution row that could not be formatted" );
305 $ret =
"<!-- Could not format Special:DeletedContribution row. -->\n";
307 $attribs[
'class'] = $classes;
308 $ret = Html::rawElement(
'li', $attribs, $ret ) .
"\n";
326 private function formatRevisionRow( $row ) {
327 $page = Title::makeTitle( $row->ar_namespace, $row->ar_title );
329 $linkRenderer = $this->getLinkRenderer();
331 $revRecord = $this->revisions[$row->ar_rev_id] ?? $this->revisionFactory->newRevisionFromArchiveRow(
333 RevisionFactory::READ_NORMAL,
340 $dellog = $linkRenderer->makeKnownLink(
342 $this->messages[
'deletionlog'],
346 'page' => $page->getPrefixedText()
350 $reviewlink = $linkRenderer->makeKnownLink(
352 $this->messages[
'undeleteviewlink']
357 if ( $this->
getAuthority()->isAllowed(
'deletedtext' ) ) {
358 $last = $linkRenderer->makeKnownLink(
360 $this->messages[
'diff'],
363 'target' => $page->getPrefixedText(),
364 'timestamp' => $revRecord->getTimestamp(),
369 $last = htmlspecialchars( $this->messages[
'diff'] );
372 $comment = $row->ar_rev_id
373 ? $this->formattedComments[$row->ar_rev_id]
374 : $this->commentFormatter->formatRevision( $revRecord, $user );
375 $date = $this->getLanguage()->userTimeAndDate( $revRecord->getTimestamp(), $user );
378 !$revRecord->userCan( RevisionRecord::DELETED_TEXT, $this->getAuthority() )
380 $link = htmlspecialchars( $date );
382 $link = $linkRenderer->makeKnownLink(
385 [
'class' =>
'mw-changeslist-date' ],
387 'target' => $page->getPrefixedText(),
388 'timestamp' => $revRecord->getTimestamp()
393 if ( $revRecord->isDeleted( RevisionRecord::DELETED_TEXT ) ) {
394 $class = Linker::getRevisionDeletedClass( $revRecord );
395 $link =
'<span class="' . $class .
'">' . $link .
'</span>';
398 $pagelink = $linkRenderer->makeLink(
401 [
'class' =>
'mw-changeslist-title' ]
404 if ( $revRecord->isMinor() ) {
411 $del = Linker::getRevDeleteLink( $user, $revRecord, $page );
416 $tools = Html::rawElement(
418 [
'class' =>
'mw-deletedcontribs-tools' ],
419 $this->msg(
'parentheses' )->rawParams( $this->getLanguage()->pipeList(
420 [ $last, $dellog, $reviewlink ] ) )->escaped()
426 'deletedcontributions',
430 $separator =
'<span class="mw-changeslist-separator">. .</span>';
431 $ret =
"{$del}{$link} {$tools} {$separator} {$mflag} {$pagelink} {$comment} {$tagSummary}";
433 # Denote if username is redacted for this edit
434 if ( $revRecord->isDeleted( RevisionRecord::DELETED_USER ) ) {
435 $ret .=
" <strong>" . $this->msg(
'rev-deleted-user-contribs' )->escaped() .
"</strong>";
438 return [ $ret, $classes ];
wfDebug( $text, $dest='all', array $context=[])
Sends a line to the debug log if enabled or, optionally, to a comment in output.
static flag( $flag, IContextSource $context=null)
Make an "<abbr>" element for a given change flag.
msg( $key,... $params)
Get a Message object with context set Parameters are the same as wfMessage()
static getTitleFor( $name, $subpage=false, $fragment='')
Get a localised Title object for a specified special page name If you don't need a full Title object,...
Interface for objects which can provide a MediaWiki context on request.