79 return $this->historyPage->getArticle();
84 return 'history page filtered';
86 return 'history page unfiltered';
95 'conds' => array_merge(
98 'options' => [
'USE INDEX' => [
'revision' =>
'page_timestamp' ] ],
102 $queryInfo[
'tables'],
103 $queryInfo[
'fields'],
105 $queryInfo[
'join_conds'],
106 $queryInfo[
'options'],
111 $historyPager = $this;
112 Hooks::run(
'PageHistoryPager::getQueryInfo', [ &$historyPager, &$queryInfo ] );
118 return 'rev_timestamp';
126 if ( $this->lastRow ) {
127 $firstInList = $this->counter == 1;
130 $notifTimestamp = $this->
getConfig()->get(
'ShowUpdatedMarker' )
134 $s = $this->
historyLine( $this->lastRow, $row, $notifTimestamp,
false, $firstInList );
138 $this->lastRow = $row;
144 if ( !Hooks::run(
'PageHistoryPager::doBatchLookups', [ $this, $this->mResult ] ) ) {
148 # Do a link batch query
149 $this->mResult->seek( 0 );
152 foreach ( $this->mResult as $row ) {
153 if ( $row->rev_parent_id ) {
154 $revIds[] = $row->rev_parent_id;
156 if ( $row->user_name !==
null ) {
157 $batch->add(
NS_USER, $row->user_name );
159 }
else { #
for anons or usernames of imported revisions
160 $batch->add(
NS_USER, $row->rev_user_text );
166 $this->mResult->seek( 0 );
175 $permissionManager = MediaWikiServices::getInstance()->getPermissionManager();
176 $this->lastRow =
false;
178 $this->oldIdChecked = 0;
180 $this->
getOutput()->wrapWikiMsg(
"<div class='mw-history-legend'>\n$1\n</div>",
'histlegend' );
181 $s = Html::openElement(
'form', [
'action' =>
wfScript(),
182 'id' =>
'mw-history-compare' ] ) .
"\n";
183 $s .= Html::hidden(
'title', $this->
getTitle()->getPrefixedDBkey() ) .
"\n";
184 $s .= Html::hidden(
'action',
'historysubmit' ) .
"\n";
185 $s .= Html::hidden(
'type',
'revision' ) .
"\n";
190 $this->buttons .= Html::openElement(
191 'div', [
'class' =>
'mw-history-compareselectedversions' ] );
192 $className =
'historysubmit mw-history-compareselectedversions-button';
193 $attrs = [
'class' => $className ]
195 $this->buttons .= $this->
submitButton( $this->
msg(
'compareselectedversions' )->text(),
201 if ( $permissionManager->userHasRight( $user,
'deleterevision' ) ) {
203 'revisiondelete',
'showhideselectedversions' );
205 if ( $this->showTagEditUI ) {
207 'editchangetags',
'history-edit-tags' );
209 if ( $actionButtons ) {
210 $this->buttons .= Xml::tags(
'div', [
'class' =>
211 'mw-history-revisionactions' ], $actionButtons );
214 if ( $permissionManager->userHasRight( $user,
'deleterevision' ) || $this->showTagEditUI ) {
218 $this->buttons .=
'</div>';
222 $s .=
'<ul id="pagehistory">' .
"\n";
229 # Note T22966, <button> is non-standard in IE<8
230 $element = Html::element(
236 'class' =>
"historysubmit mw-history-$name-button",
238 $this->
msg( $msg )->text()
244 if ( $this->lastRow ) {
245 $firstInList = $this->counter == 1;
246 if ( $this->mIsBackwards ) {
247 # Next row is unknown, but for UI reasons, probably exists if an offset has been specified
248 if ( $this->mOffset ==
'' ) {
254 # The next row is the past-the-end row
259 $notifTimestamp = $this->
getConfig()->get(
'ShowUpdatedMarker' )
263 $s = $this->
historyLine( $this->lastRow, $next, $notifTimestamp,
false, $firstInList );
268 # Add second buttons only if there is more than one rev
285 # Disable submit button if history has 1 revision only
287 return Html::submitButton( $message, $attributes );
307 function historyLine( $row, $next, $notificationtimestamp =
false,
308 $dummy =
false, $firstInList =
false ) {
309 $permissionManager = MediaWikiServices::getInstance()->getPermissionManager();
312 if ( is_object( $next ) ) {
318 $latest = $rev->getId() === $this->
getWikiPage()->getLatest();
319 $curlink = $this->
curLink( $rev );
320 $lastlink = $this->
lastLink( $rev, $next );
321 $curLastlinks = Html::rawElement(
'span', [], $curlink ) .
322 Html::rawElement(
'span', [], $lastlink );
323 $histLinks = Html::rawElement(
325 [
'class' =>
'mw-history-histlinks mw-changeslist-links' ],
329 $diffButtons = $this->
diffButtons( $rev, $firstInList );
330 $s = $histLinks . $diffButtons;
332 $link = $this->
revLink( $rev );
337 $canRevDelete = $permissionManager->userHasRight( $user,
'deleterevision' );
340 if ( $canRevDelete || $this->showTagEditUI ) {
344 if ( !$this->showTagEditUI
345 && !$rev->userCan( RevisionRecord::DELETED_RESTRICTED, $user )
347 $del = Xml::check(
'deleterevisions',
false, [
'disabled' =>
'disabled' ] );
350 $del = Xml::check(
'showhiderevisions',
false,
351 [
'name' =>
'ids[' . $rev->getId() .
']' ] );
354 } elseif ( $rev->getVisibility() &&
355 $permissionManager->userHasRight( $user,
'deletedhistory' ) ) {
357 if ( !$rev->userCan( RevisionRecord::DELETED_RESTRICTED, $user ) ) {
361 $query = [
'type' =>
'revision',
362 'target' => $this->
getTitle()->getPrefixedDBkey(),
'ids' => $rev->getId() ];
364 $rev->isDeleted( RevisionRecord::DELETED_RESTRICTED ),
false );
372 $dirmark =
$lang->getDirMark();
376 $s .=
" <span class='history-user'>" .
380 if ( $rev->isMinor() ) {
384 # Sometimes rev_len isn't populated
385 if ( $rev->getSize() !==
null ) {
386 # Size is always public data
387 $prevSize = $this->parentLens[$row->rev_parent_id] ?? 0;
390 $s .=
' <span class="mw-changeslist-separator"></span> ' .
"$fSize $sDiff";
393 # Text following the character difference is added just before running hooks
396 if ( $notificationtimestamp && ( $row->rev_timestamp >= $notificationtimestamp ) ) {
397 $s2 .=
' <span class="updatedmarker">' . $this->
msg(
'updatedmarker' )->escaped() .
'</span>';
398 $classes[] =
'mw-history-line-updated';
403 # Rollback and undo links
405 if ( $prevRev && $permissionManager->quickUserCan(
'edit', $user, $this->getTitle() ) ) {
406 if ( $latest && $permissionManager->quickUserCan(
'rollback',
407 $user, $this->getTitle() )
413 [
'verify',
'noBrackets' ]
415 if ( $rollbackLink ) {
417 $tools[] = $rollbackLink;
421 if ( !$rev->isDeleted( RevisionRecord::DELETED_TEXT )
422 && !$prevRev->isDeleted( RevisionRecord::DELETED_TEXT )
424 # Create undo tooltip for the first (=latest) line only
425 $undoTooltip = $latest
426 ? [
'title' => $this->
msg(
'tooltip-undo' )->text() ]
430 $this->
msg(
'editundo' )->text(),
434 'undoafter' => $prevRev->getId(),
435 'undo' => $rev->getId()
438 $tools[] =
"<span class=\"mw-history-undo\">{$undolink}</span>";
442 Hooks::run(
'HistoryRevisionTools', [ $rev, &$tools, $prevRev, $user ] );
445 $s2 .=
' ' . Html::openElement(
'span', [
'class' =>
'mw-changeslist-links' ] );
446 foreach ( $tools as $tool ) {
447 $s2 .= Html::rawElement(
'span', [], $tool );
449 $s2 .= Html::closeElement(
'span' );
458 $classes = array_merge( $classes, $newClasses );
459 if ( $tagSummary !==
'' ) {
460 $s2 .=
" $tagSummary";
463 # Include separator between character difference and following text
465 $s .=
' <span class="mw-changeslist-separator"></span> ' . $s2;
468 $attribs = [
'data-mw-revid' => $rev->getId() ];
470 Hooks::run(
'PageHistoryLineEnding', [ $this, &$row, &
$s, &$classes, &$attribs ] );
471 $attribs = array_filter( $attribs,
472 [ Sanitizer::class,
'isReservedDataAttribute' ],
477 $attribs[
'class'] = implode(
' ', $classes );
480 return Xml::tags(
'li', $attribs,
$s ) .
"\n";
501 $cur = $this->historyPage->message[
'cur'];
503 if ( $latest === $rev->getId()
504 || !$rev->userCan( RevisionRecord::DELETED_TEXT, $this->getUser() )
514 'oldid' => $rev->getId()
530 $last = $this->historyPage->message[
'last'];
532 if ( $next ===
null ) {
533 # Probably no next row
538 if ( $next ===
'unknown' ) {
539 # Next row probably exists but is unknown, use an oldid=prev link
545 'diff' => $prevRev->getId(),
553 if ( !$prevRev->userCan( RevisionRecord::DELETED_TEXT, $this->getUser() )
554 || !$nextRev->userCan( RevisionRecord::DELETED_TEXT, $this->getUser() )
564 'diff' => $prevRev->getId(),
565 'oldid' => $next->rev_id
581 $radio = [
'type' =>
'radio',
'value' => $id ];
583 if ( $firstInList ) {
584 $first = Xml::element(
'input',
585 array_merge( $radio, [
586 'style' =>
'visibility:hidden',
588 'id' =>
'mw-oldid-null' ] )
590 $checkmark = [
'checked' =>
'checked' ];
592 # Check visibility of old revisions
593 if ( !$rev->userCan( RevisionRecord::DELETED_TEXT, $this->getUser() ) ) {
594 $radio[
'disabled'] =
'disabled';
596 } elseif ( !$this->oldIdChecked ) {
597 $checkmark = [
'checked' =>
'checked' ];
598 $this->oldIdChecked = $id;
602 $first = Xml::element(
'input',
603 array_merge( $radio, $checkmark, [
605 'id' =>
"mw-oldid-$id" ] ) );
608 $second = Xml::element(
'input',
609 array_merge( $radio, $checkmark, [
611 'id' =>
"mw-diff-$id" ] ) );
613 return $first . $second;
623 parent::getDefaultQuery();
624 unset( $this->mDefaultQuery[
'date-range-to'] );
wfScript( $script='index')
Get the path to a specified script file, respecting file extensions; this is a wrapper around $wgScri...
static showCharacterDifference( $old, $new, IContextSource $context=null)
Show formatted char difference.
static flag( $flag, IContextSource $context=null)
Make an "<abbr>" element for a given change flag.
static revDateLink(Revision $rev, User $user, Language $lang, $title=null)
Render the date and time of a revision in the current user language based on whether the user is able...
msg( $key,... $params)
Get a Message object with context set Parameters are the same as wfMessage()
getWikiPage()
Get the WikiPage object.
getContext()
Get the base IContextSource object.
This class handles printing the history page for an article.
Marks HTML that shouldn't be escaped.
Class representing a list of titles The execute() method checks them all for existence and adds them ...
static generateRollback( $rev, IContextSource $context=null, $options=[ 'verify'])
Generate a rollback link for a given revision.
static revComment(Revision $rev, $local=false, $isPublic=false, $useParentheses=true)
Wrap and format the given revision's comment block, if the current user is allowed to view it.
static revDeleteLinkDisabled( $delete=true)
Creates a dead (show/hide) link for deleting revisions/log entries.
static formatRevisionSize( $size)
static revUserTools( $rev, $isPublic=false, $useParentheses=true)
Generate a user tool link cluster if the current user is allowed to view it.
static tooltipAndAccesskeyAttribs( $name, array $msgParams=[], $options=null)
Returns the attributes for the tooltip and access key.
static revDeleteLink( $query=[], $restricted=false, $delete=true)
Creates a (show/hide) link for deleting revisions/log entries.
Class for generating clickable toggle links for a list of checkboxes.
static getQueryInfo( $options=[])
Return the tables, fields, and join conditions to be selected to create a new revision object.
static getParentLengths( $db, array $revIds)
Do a batched query to get the parent revision lengths.
if(!isset( $args[0])) $lang