MediaWiki  master
HistoryPager.php
Go to the documentation of this file.
1 <?php
31 
37 
38  public $mGroupByDate = true;
39 
41 
42  protected $oldIdChecked;
43 
44  protected $preventClickjacking = false;
48  protected $parentLens;
49 
51  protected $showTagEditUI;
52 
54  private $tagFilter;
55 
57  private $revisionStore;
58 
60  private $watchlistManager;
61 
63  private $linkBatchFactory;
64 
66  private $commentFormatter;
67 
71  private $revisions = [];
72 
76  private $formattedComments = [];
77 
89  public function __construct(
91  $year = 0,
92  $month = 0,
93  $tagFilter = '',
94  array $conds = [],
95  $day = 0,
96  LinkBatchFactory $linkBatchFactory = null,
97  WatchlistManager $watchlistManager = null,
98  CommentFormatter $commentFormatter = null
99  ) {
100  parent::__construct( $historyPage->getContext() );
101  $this->historyPage = $historyPage;
102  $this->tagFilter = $tagFilter;
103  $this->getDateCond( $year, $month, $day );
104  $this->conds = $conds;
105  $this->showTagEditUI = ChangeTags::showTagEditingUI( $this->getAuthority() );
106  $services = MediaWikiServices::getInstance();
107  $this->revisionStore = $services->getRevisionStore();
108  $this->linkBatchFactory = $linkBatchFactory ?? $services->getLinkBatchFactory();
109  $this->watchlistManager = $watchlistManager
110  ?? $services->getWatchlistManager();
111  $this->commentFormatter = $commentFormatter ?? $services->getCommentFormatter();
112  }
113 
114  // For hook compatibility...
115  public function getArticle() {
116  return $this->historyPage->getArticle();
117  }
118 
119  protected function getSqlComment() {
120  if ( $this->conds ) {
121  return 'history page filtered'; // potentially slow, see CR r58153
122  } else {
123  return 'history page unfiltered';
124  }
125  }
126 
127  public function getQueryInfo() {
128  $revQuery = $this->revisionStore->getQueryInfo( [ 'user' ] );
129 
130  $queryInfo = [
131  'tables' => $revQuery['tables'],
132  'fields' => $revQuery['fields'],
133  'conds' => array_merge(
134  [ 'rev_page' => $this->getWikiPage()->getId() ],
135  $this->conds ),
136  'options' => [ 'USE INDEX' => [ 'revision' => 'rev_page_timestamp' ] ],
137  'join_conds' => $revQuery['joins'],
138  ];
140  $queryInfo['tables'],
141  $queryInfo['fields'],
142  $queryInfo['conds'],
143  $queryInfo['join_conds'],
144  $queryInfo['options'],
145  $this->tagFilter
146  );
147 
148  $this->getHookRunner()->onPageHistoryPager__getQueryInfo( $this, $queryInfo );
149 
150  return $queryInfo;
151  }
152 
153  public function getIndexField() {
154  return [ [ 'rev_timestamp', 'rev_id' ] ];
155  }
156 
161  public function formatRow( $row ) {
162  $notifTimestamp = $this->getConfig()->get( MainConfigNames::ShowUpdatedMarker )
163  ? $this->watchlistManager
164  ->getTitleNotificationTimestamp( $this->getUser(), $this->getTitle() )
165  : false;
166 
167  return $this->historyLine( $row, $notifTimestamp, $this->getResultOffset() );
168  }
169 
170  protected function doBatchLookups() {
171  if ( !$this->getHookRunner()->onPageHistoryPager__doBatchLookups( $this, $this->mResult ) ) {
172  return;
173  }
174 
175  # Do a link batch query
176  $batch = $this->linkBatchFactory->newLinkBatch();
177  $revIds = [];
178  $title = $this->getTitle();
179  foreach ( $this->mResult as $row ) {
180  if ( $row->rev_parent_id ) {
181  $revIds[] = (int)$row->rev_parent_id;
182  }
183  if ( $row->user_name !== null ) {
184  $batch->add( NS_USER, $row->user_name );
185  $batch->add( NS_USER_TALK, $row->user_name );
186  } else { # for anons or usernames of imported revisions
187  $batch->add( NS_USER, $row->rev_user_text );
188  $batch->add( NS_USER_TALK, $row->rev_user_text );
189  }
190  $this->revisions[] = $this->revisionStore->newRevisionFromRow(
191  $row,
192  RevisionStore::READ_NORMAL,
193  $title
194  );
195  }
196  $this->parentLens = $this->revisionStore->getRevisionSizes( $revIds );
197  $batch->execute();
198 
199  # The keys of $this->formattedComments will be the same as the keys of $this->revisions
200  $this->formattedComments = $this->commentFormatter->createRevisionBatch()
201  ->revisions( $this->revisions )
202  ->authority( $this->getAuthority() )
203  ->samePage( false )
204  ->hideIfDeleted( true )
205  ->useParentheses( false )
206  ->execute();
207 
208  $this->mResult->seek( 0 );
209  }
210 
215  protected function getEmptyBody() {
216  return $this->msg( 'history-empty' )->escaped();
217  }
218 
224  protected function getStartBody() {
225  $this->oldIdChecked = 0;
226  $s = '';
227  // Button container stored in $this->buttons for re-use in getEndBody()
228  $this->buttons = '';
229  if ( $this->getNumRows() > 0 ) {
230  $this->getOutput()->wrapWikiMsg( "<div class='mw-history-legend'>\n$1\n</div>", 'histlegend' );
231  $s = Html::openElement( 'form', [
232  'action' => wfScript(),
233  'id' => 'mw-history-compare'
234  ] ) . "\n";
235  $s .= Html::hidden( 'title', $this->getTitle()->getPrefixedDBkey() ) . "\n";
236  $s .= Html::hidden( 'action', 'historysubmit' ) . "\n";
237  $s .= Html::hidden( 'type', 'revision' ) . "\n";
238 
239  $this->buttons .= Html::openElement(
240  'div', [ 'class' => 'mw-history-compareselectedversions' ] );
241  $className = 'historysubmit mw-history-compareselectedversions-button mw-ui-button';
242  $attrs = [ 'class' => $className ]
243  + Linker::tooltipAndAccesskeyAttribs( 'compareselectedversions' );
244  $this->buttons .= $this->submitButton( $this->msg( 'compareselectedversions' )->text(),
245  $attrs
246  ) . "\n";
247 
248  $actionButtons = '';
249  if ( $this->getAuthority()->isAllowed( 'deleterevision' ) ) {
250  $actionButtons .= $this->getRevisionButton(
251  'revisiondelete', 'showhideselectedversions' );
252  }
253  if ( $this->showTagEditUI ) {
254  $actionButtons .= $this->getRevisionButton(
255  'editchangetags', 'history-edit-tags' );
256  }
257  if ( $actionButtons ) {
258  $this->buttons .= Xml::tags( 'div', [ 'class' =>
259  'mw-history-revisionactions' ], $actionButtons );
260  }
261 
262  if ( $this->getAuthority()->isAllowed( 'deleterevision' ) || $this->showTagEditUI ) {
263  $this->buttons .= ( new ListToggle( $this->getOutput() ) )->getHTML();
264  }
265 
266  $this->buttons .= '</div>';
267 
268  $s .= $this->buttons;
269  }
270 
271  $s .= '<section id="pagehistory" class="mw-pager-body">';
272 
273  return $s;
274  }
275 
276  private function getRevisionButton( $name, $msg ) {
277  $this->setPreventClickjacking( true );
278  $element = Html::element(
279  'button',
280  [
281  'type' => 'submit',
282  'name' => $name,
283  'value' => '1',
284  'class' => "historysubmit mw-history-$name-button mw-ui-button",
285  ],
286  $this->msg( $msg )->text()
287  ) . "\n";
288  return $element;
289  }
290 
291  protected function getEndBody() {
292  if ( $this->getNumRows() == 0 ) {
293  return '';
294  }
295  $s = '';
296  # Add second buttons only if there is more than one rev
297  if ( $this->getNumRows() > 2 ) {
298  $s .= $this->buttons;
299  }
300  $s .= '</section>'; // closes section#pagehistory
301  $s .= '</form>';
302  return $s;
303  }
304 
312  private function submitButton( $message, $attributes = [] ) {
313  # Disable submit button if history has 1 revision only
314  if ( $this->getNumRows() > 1 ) {
315  return Html::submitButton( $message, $attributes );
316  } else {
317  return '';
318  }
319  }
320 
331  private function historyLine( $row, $notificationtimestamp, $resultOffset ) {
332  $numRows = min( $this->mResult->numRows(), $this->mLimit );
333 
334  $firstInList = $resultOffset === ( $this->mIsBackwards ? $numRows - 1 : 0 );
335  // Next in the list, previous in chronological order.
336  $nextResultOffset = $resultOffset + ( $this->mIsBackwards ? -1 : 1 );
337 
338  $revRecord = $this->revisions[$resultOffset];
339  // This may only be null if the current line is the last one in the list.
340  $previousRevRecord = $this->revisions[$nextResultOffset] ?? null;
341 
342  $latest = $revRecord->getId() === $this->getWikiPage()->getLatest();
343  $curlink = $this->curLink( $revRecord );
344  if ( $previousRevRecord ) {
345  // Display a link to compare to the previous revision
346  $lastlink = $this->lastLink( $revRecord, $previousRevRecord );
347  } elseif ( $this->mIsBackwards && $this->mOffset !== '' ) {
348  // When paging "backwards", we don't have the extra result for the next revision that would
349  // appear in the list, and we don't know whether this is the oldest revision or not.
350  // However, if an offset has been specified, then the user probably reached this page by
351  // navigating from the "next" page, therefore the next revision probably exists.
352  // Display a link using &oldid=prev (this skips some checks but that's fine).
353  $lastlink = $this->lastLink( $revRecord, null );
354  } else {
355  // Do not display a link, because this is the oldest revision of the page
356  $lastlink = $this->historyPage->message['last'];
357  }
358  $curLastlinks = Html::rawElement( 'span', [], $curlink ) .
359  Html::rawElement( 'span', [], $lastlink );
360  $histLinks = Html::rawElement(
361  'span',
362  [ 'class' => 'mw-history-histlinks mw-changeslist-links' ],
363  $curLastlinks
364  );
365 
366  $diffButtons = $this->diffButtons( $revRecord, $firstInList );
367  $s = $histLinks . $diffButtons;
368 
369  $link = $this->revLink( $revRecord );
370  $classes = [];
371 
372  $del = '';
373  $user = $this->getUser();
374  $canRevDelete = $this->getAuthority()->isAllowed( 'deleterevision' );
375  // Show checkboxes for each revision, to allow for revision deletion and
376  // change tags
377  if ( $canRevDelete || $this->showTagEditUI ) {
378  $this->setPreventClickjacking( true );
379  // If revision was hidden from sysops and we don't need the checkbox
380  // for anything else, disable it
381  if ( !$this->showTagEditUI
382  && !$revRecord->userCan( RevisionRecord::DELETED_RESTRICTED, $this->getAuthority() )
383  ) {
384  $del = Xml::check( 'deleterevisions', false, [ 'disabled' => 'disabled' ] );
385  // Otherwise, enable the checkbox...
386  } else {
387  $del = Xml::check( 'showhiderevisions', false,
388  [ 'name' => 'ids[' . $revRecord->getId() . ']' ] );
389  }
390  // User can only view deleted revisions...
391  } elseif ( $revRecord->getVisibility() && $this->getAuthority()->isAllowed( 'deletedhistory' ) ) {
392  // If revision was hidden from sysops, disable the link
393  if ( !$revRecord->userCan( RevisionRecord::DELETED_RESTRICTED, $this->getAuthority() ) ) {
394  $del = Linker::revDeleteLinkDisabled( false );
395  // Otherwise, show the link...
396  } else {
397  $query = [
398  'type' => 'revision',
399  'target' => $this->getTitle()->getPrefixedDBkey(),
400  'ids' => $revRecord->getId()
401  ];
402  $del .= Linker::revDeleteLink(
403  $query,
404  $revRecord->isDeleted( RevisionRecord::DELETED_RESTRICTED ),
405  false
406  );
407  }
408  }
409  if ( $del ) {
410  $s .= " $del ";
411  }
412 
413  $lang = $this->getLanguage();
414  $dirmark = $lang->getDirMark();
415 
416  $s .= " $link";
417  $s .= $dirmark;
418  $s .= " <span class='history-user'>" .
419  Linker::revUserTools( $revRecord, true, false ) . "</span>";
420  $s .= $dirmark;
421 
422  if ( $revRecord->isMinor() ) {
423  $s .= ' ' . ChangesList::flag( 'minor', $this->getContext() );
424  }
425 
426  # Sometimes rev_len isn't populated
427  if ( $revRecord->getSize() !== null ) {
428  # Size is always public data
429  $prevSize = $this->parentLens[$row->rev_parent_id] ?? 0;
430  $sDiff = ChangesList::showCharacterDifference( $prevSize, $revRecord->getSize() );
431  $fSize = Linker::formatRevisionSize( $revRecord->getSize() );
432  $s .= ' <span class="mw-changeslist-separator"></span> ' . "$fSize $sDiff";
433  }
434 
435  # Text following the character difference is added just before running hooks
436  $s2 = $this->formattedComments[$resultOffset];
437 
438  if ( $s2 === '' ) {
439  $defaultComment = $this->msg( 'changeslist-nocomment' )->escaped();
440  $s2 = "<span class=\"comment mw-comment-none\">$defaultComment</span>";
441  }
442 
443  if ( $notificationtimestamp && ( $row->rev_timestamp >= $notificationtimestamp ) ) {
444  $s2 .= ' <span class="updatedmarker">' . $this->msg( 'updatedmarker' )->escaped() . '</span>';
445  $classes[] = 'mw-history-line-updated';
446  }
447 
448  $tools = [];
449 
450  # Rollback and undo links
451 
452  if ( $previousRevRecord && $this->getAuthority()->probablyCan( 'edit', $this->getTitle() ) ) {
453  if ( $latest && $this->getAuthority()->probablyCan( 'rollback', $this->getTitle() )
454  ) {
455  // Get a rollback link without the brackets
456  $rollbackLink = Linker::generateRollback(
457  $revRecord,
458  $this->getContext(),
459  [ 'verify', 'noBrackets' ]
460  );
461  if ( $rollbackLink ) {
462  $this->setPreventClickjacking( true );
463  $tools[] = $rollbackLink;
464  }
465  }
466 
467  if ( !$revRecord->isDeleted( RevisionRecord::DELETED_TEXT )
468  && !$previousRevRecord->isDeleted( RevisionRecord::DELETED_TEXT )
469  ) {
470  # Create undo tooltip for the first (=latest) line only
471  $undoTooltip = $latest
472  ? [ 'title' => $this->msg( 'tooltip-undo' )->text() ]
473  : [];
474  $undolink = $this->getLinkRenderer()->makeKnownLink(
475  $this->getTitle(),
476  $this->msg( 'editundo' )->text(),
477  $undoTooltip,
478  [
479  'action' => 'edit',
480  'undoafter' => $previousRevRecord->getId(),
481  'undo' => $revRecord->getId()
482  ]
483  );
484  $tools[] = "<span class=\"mw-history-undo\">{$undolink}</span>";
485  }
486  }
487  // Allow extension to add their own links here
488  $this->getHookRunner()->onHistoryTools(
489  $revRecord,
490  $tools,
491  $previousRevRecord,
492  $user
493  );
494 
495  if ( $tools ) {
496  $s2 .= ' ' . Html::openElement( 'span', [ 'class' => 'mw-changeslist-links' ] );
497  foreach ( $tools as $tool ) {
498  $s2 .= Html::rawElement( 'span', [], $tool );
499  }
500  $s2 .= Html::closeElement( 'span' );
501  }
502 
503  # Tags
504  list( $tagSummary, $newClasses ) = ChangeTags::formatSummaryRow(
505  $row->ts_tags,
506  'history',
507  $this->getContext()
508  );
509  $classes = array_merge( $classes, $newClasses );
510  if ( $tagSummary !== '' ) {
511  $s2 .= " $tagSummary";
512  }
513 
514  # Include separator between character difference and following text
515  $s .= ' <span class="mw-changeslist-separator"></span> ' . $s2;
516 
517  $attribs = [ 'data-mw-revid' => $revRecord->getId() ];
518 
519  $this->getHookRunner()->onPageHistoryLineEnding( $this, $row, $s, $classes, $attribs );
520  $attribs = array_filter( $attribs,
521  [ Sanitizer::class, 'isReservedDataAttribute' ],
522  ARRAY_FILTER_USE_KEY
523  );
524 
525  if ( $classes ) {
526  $attribs['class'] = implode( ' ', $classes );
527  }
528 
529  return Xml::tags( 'li', $attribs, $s ) . "\n";
530  }
531 
538  private function revLink( RevisionRecord $rev ) {
539  return ChangesList::revDateLink( $rev, $this->getAuthority(), $this->getLanguage(),
540  $this->getTitle() );
541  }
542 
549  private function curLink( RevisionRecord $rev ) {
550  $cur = $this->historyPage->message['cur'];
551  $latest = $this->getWikiPage()->getLatest();
552  if ( $latest === $rev->getId()
553  || !$rev->userCan( RevisionRecord::DELETED_TEXT, $this->getAuthority() )
554  ) {
555  return $cur;
556  } else {
557  return $this->getLinkRenderer()->makeKnownLink(
558  $this->getTitle(),
559  new HtmlArmor( $cur ),
560  [
561  'title' => $this->historyPage->message['tooltip-cur']
562  ],
563  [
564  'diff' => $latest,
565  'oldid' => $rev->getId()
566  ]
567  );
568  }
569  }
570 
579  private function lastLink( RevisionRecord $prevRev, ?RevisionRecord $nextRev ) {
580  $last = $this->historyPage->message['last'];
581 
582  if ( !$prevRev->userCan( RevisionRecord::DELETED_TEXT, $this->getAuthority() ) ||
583  ( $nextRev && !$nextRev->userCan( RevisionRecord::DELETED_TEXT, $this->getAuthority() ) )
584  ) {
585  return $last;
586  }
587 
588  return $this->getLinkRenderer()->makeKnownLink(
589  $this->getTitle(),
590  new HtmlArmor( $last ),
591  [
592  'title' => $this->historyPage->message['tooltip-last']
593  ],
594  [
595  'diff' => $prevRev->getId(),
596  'oldid' => $nextRev ? $nextRev->getId() : 'prev'
597  ]
598  );
599  }
600 
609  private function diffButtons( RevisionRecord $rev, $firstInList ) {
610  if ( $this->getNumRows() > 1 ) {
611  $id = $rev->getId();
612  $radio = [ 'type' => 'radio', 'value' => $id ];
614  if ( $firstInList ) {
615  $first = Xml::element( 'input',
616  array_merge( $radio, [
617  // Disable the hidden radio because it can still
618  // be selected with arrow keys on Firefox
619  'disabled' => '',
620  'name' => 'oldid',
621  'id' => 'mw-oldid-null' ] )
622  );
623  $checkmark = [ 'checked' => 'checked' ];
624  } else {
625  # Check visibility of old revisions
626  if ( !$rev->userCan( RevisionRecord::DELETED_TEXT, $this->getAuthority() ) ) {
627  $radio['disabled'] = 'disabled';
628  $checkmark = []; // We will check the next possible one
629  } elseif ( !$this->oldIdChecked ) {
630  $checkmark = [ 'checked' => 'checked' ];
631  $this->oldIdChecked = $id;
632  } else {
633  $checkmark = [];
634  }
635  $first = Xml::element( 'input',
636  array_merge( $radio, $checkmark, [
637  'name' => 'oldid',
638  'id' => "mw-oldid-$id" ] ) );
639  $checkmark = [];
640  }
641  $second = Xml::element( 'input',
642  array_merge( $radio, $checkmark, [
643  'name' => 'diff',
644  'id' => "mw-diff-$id" ] ) );
645 
646  return $first . $second;
647  } else {
648  return '';
649  }
650  }
651 
657  protected function isNavigationBarShown() {
658  if ( $this->getNumRows() == 0 ) {
659  return false;
660  }
661  return parent::isNavigationBarShown();
662  }
663 
667  public function getDefaultQuery() {
668  parent::getDefaultQuery();
669  unset( $this->mDefaultQuery['date-range-to'] );
670  return $this->mDefaultQuery;
671  }
672 
678  private function setPreventClickjacking( bool $flag ) {
679  $this->preventClickjacking = $flag;
680  }
681 
686  public function getPreventClickjacking() {
688  }
689 
690 }
const NS_USER
Definition: Defines.php:66
const NS_USER_TALK
Definition: Defines.php:67
wfScript( $script='index')
Get the path to a specified script file, respecting file extensions; this is a wrapper around $wgScri...
static modifyDisplayQuery(&$tables, &$fields, &$conds, &$join_conds, &$options, $filter_tag='', bool $exclude=false)
Applies all tags-related changes to a query.
Definition: ChangeTags.php:906
static showTagEditingUI(Authority $performer)
Indicate whether change tag editing UI is relevant.
static formatSummaryRow( $tags, $page, MessageLocalizer $localizer=null)
Creates HTML for the given tags.
Definition: ChangeTags.php:193
static revDateLink(RevisionRecord $rev, Authority $performer, Language $lang, $title=null)
Render the date and time of a revision in the current user language based on whether the user is able...
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.
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.
doBatchLookups()
Called from getBody(), before getStartBody() is called and after doQuery() was called.
formatRow( $row)
isNavigationBarShown()
Returns whether to show the "navigation bar".
getEndBody()
Hook into getBody() for the end of the list.
getDefaultQuery()
@inheritDoc
__construct(HistoryAction $historyPage, $year=0, $month=0, $tagFilter='', array $conds=[], $day=0, LinkBatchFactory $linkBatchFactory=null, WatchlistManager $watchlistManager=null, CommentFormatter $commentFormatter=null)
array $parentLens
bool $showTagEditUI
Whether to show the tag editing UI.
getSqlComment()
Get some text to go in brackets in the "function name" part of the SQL comment.
getPreventClickjacking()
Get the "prevent clickjacking" flag.
getIndexField()
Returns the name of the index field.
getQueryInfo()
Provides all parameters needed for the main paged query.
getStartBody()
Creates begin of history list with a submit button.
getEmptyBody()
Returns message when query returns no revisions.
Marks HTML that shouldn't be escaped.
Definition: HtmlArmor.php:30
static element( $element, $attribs=[], $contents='')
Identical to rawElement(), but HTML-escapes $contents (like Xml::element()).
Definition: Html.php:236
static submitButton( $contents, array $attrs, array $modifiers=[])
Returns an HTML link element in a string styled as a button (when $wgUseMediaWikiUIEverywhere is enab...
Definition: Html.php:190
static rawElement( $element, $attribs=[], $contents='')
Returns an HTML element in a string.
Definition: Html.php:214
static openElement( $element, $attribs=[])
Identical to rawElement(), but has no third parameter and omits the end tag (and the self-closing '/'...
Definition: Html.php:256
static closeElement( $element)
Returns "</$element>".
Definition: Html.php:320
static hidden( $name, $value, array $attribs=[])
Convenience function to produce an input element with type=hidden.
Definition: Html.php:851
array $mDefaultQuery
Definition: IndexPager.php:149
getNumRows()
Get the number of rows in the result set.
Definition: IndexPager.php:777
static revDeleteLinkDisabled( $delete=true)
Creates a dead (show/hide) link for deleting revisions/log entries.
Definition: Linker.php:2185
static generateRollback(RevisionRecord $revRecord, IContextSource $context=null, $options=[ 'verify'])
Generate a rollback link for a given revision.
Definition: Linker.php:1790
static formatRevisionSize( $size)
Definition: Linker.php:1579
static revUserTools(RevisionRecord $revRecord, $isPublic=false, $useParentheses=true)
Generate a user tool link cluster if the current user is allowed to view it.
Definition: Linker.php:1327
static revDeleteLink( $query=[], $restricted=false, $delete=true)
Creates a (show/hide) link for deleting revisions/log entries.
Definition: Linker.php:2161
static tooltipAndAccesskeyAttribs( $name, array $msgParams=[], $options=null, $localizer=null, $user=null, $config=null, $relevantTitle=null)
Returns the attributes for the tooltip and access key.
Definition: Linker.php:2255
Class for generating clickable toggle links for a list of checkboxes.
Definition: ListToggle.php:31
This is the main service interface for converting single-line comments from various DB comment fields...
A class containing constants representing the names of configuration variables.
Service locator for MediaWiki core services.
Page revision base class.
userCan( $field, Authority $performer)
Determine if the give authority is allowed to view a particular field of this revision,...
getId( $wikiId=self::LOCAL)
Get revision ID.
Service for looking up page revisions.
Efficient paging for SQL queries.
getDateCond( $year, $month, $day=-1)
Set and return the mOffset timestamp such that we can get all revisions with a timestamp up to the sp...
static check( $name, $checked=false, $attribs=[])
Convenience function to build an HTML checkbox.
Definition: Xml.php:332
static tags( $element, $attribs, $contents)
Same as Xml::element(), but does not escape contents.
Definition: Xml.php:134
static element( $element, $attribs=null, $contents='', $allowShortTag=true)
Format an XML element with given attributes and, optionally, text content.
Definition: Xml.php:43
foreach( $mmfl['setupFiles'] as $fileName) if( $queue) if(empty( $mmfl['quiet'])) $s
if(!isset( $args[0])) $lang
$revQuery