MediaWiki  1.32.0
Article.php
Go to the documentation of this file.
1 <?php
26 
38 class Article implements Page {
43  protected $mContext;
44 
46  protected $mPage;
47 
53 
63 
70  public $mContentLoaded = false;
71 
77  public $mOldId;
78 
80  public $mRedirectedFrom = null;
81 
83  public $mRedirectUrl = false;
84 
90  public $mRevIdFetched = 0;
91 
100  private $fetchResult = null;
101 
109  public $mRevision = null;
110 
116  public $mParserOutput = null;
117 
124 
130  public function __construct( Title $title, $oldId = null ) {
131  $this->mOldId = $oldId;
132  $this->mPage = $this->newPage( $title );
133  }
134 
139  protected function newPage( Title $title ) {
140  return new WikiPage( $title );
141  }
142 
148  public static function newFromID( $id ) {
149  $t = Title::newFromID( $id );
150  return $t == null ? null : new static( $t );
151  }
152 
160  public static function newFromTitle( $title, IContextSource $context ) {
161  if ( NS_MEDIA == $title->getNamespace() ) {
162  // XXX: This should not be here, but where should it go?
163  $title = Title::makeTitle( NS_FILE, $title->getDBkey() );
164  }
165 
166  $page = null;
167  Hooks::run( 'ArticleFromTitle', [ &$title, &$page, $context ] );
168  if ( !$page ) {
169  switch ( $title->getNamespace() ) {
170  case NS_FILE:
171  $page = new ImagePage( $title );
172  break;
173  case NS_CATEGORY:
174  $page = new CategoryPage( $title );
175  break;
176  default:
177  $page = new Article( $title );
178  }
179  }
180  $page->setContext( $context );
181 
182  return $page;
183  }
184 
192  public static function newFromWikiPage( WikiPage $page, IContextSource $context ) {
194  $article->mPage = $page; // override to keep process cached vars
195  return $article;
196  }
197 
203  public function getRedirectedFrom() {
204  return $this->mRedirectedFrom;
205  }
206 
212  public function setRedirectedFrom( Title $from ) {
213  $this->mRedirectedFrom = $from;
214  }
215 
221  public function getTitle() {
222  return $this->mPage->getTitle();
223  }
224 
231  public function getPage() {
232  return $this->mPage;
233  }
234 
238  public function clear() {
239  $this->mContentLoaded = false;
240 
241  $this->mRedirectedFrom = null; # Title object if set
242  $this->mRevIdFetched = 0;
243  $this->mRedirectUrl = false;
244  $this->mRevision = null;
245  $this->mContentObject = null;
246  $this->fetchResult = null;
247 
248  // TODO hard-deprecate direct access to public fields
249 
250  $this->mPage->clear();
251  }
252 
270  protected function getContentObject() {
271  if ( $this->mPage->getId() === 0 ) {
272  $content = $this->getSubstituteContent();
273  } else {
274  $this->fetchContentObject();
276  }
277 
278  return $content;
279  }
280 
286  private function getSubstituteContent() {
287  # If this is a MediaWiki:x message, then load the messages
288  # and return the message value for x.
289  if ( $this->getTitle()->getNamespace() == NS_MEDIAWIKI ) {
290  $text = $this->getTitle()->getDefaultMessageText();
291  if ( $text === false ) {
292  $text = '';
293  }
294 
295  $content = ContentHandler::makeContent( $text, $this->getTitle() );
296  } else {
297  $message = $this->getContext()->getUser()->isLoggedIn() ? 'noarticletext' : 'noarticletextanon';
298  $content = new MessageContent( $message, null, 'parsemag' );
299  }
300 
301  return $content;
302  }
303 
314  $content = $this->getSubstituteContent();
315 
316  return $content->getParserOutput( $this->getTitle(), 0, $options );
317  }
318 
326  public function getOldID() {
327  if ( is_null( $this->mOldId ) ) {
328  $this->mOldId = $this->getOldIDFromRequest();
329  }
330 
331  return $this->mOldId;
332  }
333 
339  public function getOldIDFromRequest() {
340  $this->mRedirectUrl = false;
341 
342  $request = $this->getContext()->getRequest();
343  $oldid = $request->getIntOrNull( 'oldid' );
344 
345  if ( $oldid === null ) {
346  return 0;
347  }
348 
349  if ( $oldid !== 0 ) {
350  # Load the given revision and check whether the page is another one.
351  # In that case, update this instance to reflect the change.
352  if ( $oldid === $this->mPage->getLatest() ) {
353  $this->mRevision = $this->mPage->getRevision();
354  } else {
355  $this->mRevision = Revision::newFromId( $oldid );
356  if ( $this->mRevision !== null ) {
357  // Revision title doesn't match the page title given?
358  if ( $this->mPage->getId() != $this->mRevision->getPage() ) {
359  $function = get_class( $this->mPage ) . '::newFromID';
360  $this->mPage = $function( $this->mRevision->getPage() );
361  }
362  }
363  }
364  }
365 
366  if ( $request->getVal( 'direction' ) == 'next' ) {
367  $nextid = $this->getTitle()->getNextRevisionID( $oldid );
368  if ( $nextid ) {
369  $oldid = $nextid;
370  $this->mRevision = null;
371  } else {
372  $this->mRedirectUrl = $this->getTitle()->getFullURL( 'redirect=no' );
373  }
374  } elseif ( $request->getVal( 'direction' ) == 'prev' ) {
375  $previd = $this->getTitle()->getPreviousRevisionID( $oldid );
376  if ( $previd ) {
377  $oldid = $previd;
378  $this->mRevision = null;
379  }
380  }
381 
382  $this->mRevIdFetched = $this->mRevision ? $this->mRevision->getId() : 0;
383 
384  return $oldid;
385  }
386 
400  protected function fetchContentObject() {
401  if ( !$this->mContentLoaded ) {
402  $this->fetchRevisionRecord();
403  }
404 
405  return $this->mContentObject;
406  }
407 
417  protected function fetchRevisionRecord() {
418  if ( $this->fetchResult ) {
419  return $this->mRevision ? $this->mRevision->getRevisionRecord() : null;
420  }
421 
422  $this->mContentLoaded = true;
423  $this->mContentObject = null;
424 
425  $oldid = $this->getOldID();
426 
427  // $this->mRevision might already be fetched by getOldIDFromRequest()
428  if ( !$this->mRevision ) {
429  if ( !$oldid ) {
430  $this->mRevision = $this->mPage->getRevision();
431 
432  if ( !$this->mRevision ) {
433  wfDebug( __METHOD__ . " failed to find page data for title " .
434  $this->getTitle()->getPrefixedText() . "\n" );
435 
436  // Just for sanity, output for this case is done by showMissingArticle().
437  $this->fetchResult = Status::newFatal( 'noarticletext' );
438  $this->applyContentOverride( $this->makeFetchErrorContent() );
439  return null;
440  }
441  } else {
442  $this->mRevision = Revision::newFromId( $oldid );
443 
444  if ( !$this->mRevision ) {
445  wfDebug( __METHOD__ . " failed to load revision, rev_id $oldid\n" );
446 
447  $this->fetchResult = Status::newFatal( 'missing-revision', $oldid );
448  $this->applyContentOverride( $this->makeFetchErrorContent() );
449  return null;
450  }
451  }
452  }
453 
454  $this->mRevIdFetched = $this->mRevision->getId();
455  $this->fetchResult = Status::newGood( $this->mRevision );
456 
457  if ( !$this->mRevision->userCan( Revision::DELETED_TEXT, $this->getContext()->getUser() ) ) {
458  wfDebug( __METHOD__ . " failed to retrieve content of revision " .
459  $this->mRevision->getId() . "\n" );
460 
461  // Just for sanity, output for this case is done by showDeletedRevisionHeader().
462  $this->fetchResult = Status::newFatal( 'rev-deleted-text-permission' );
463  $this->applyContentOverride( $this->makeFetchErrorContent() );
464  return null;
465  }
466 
467  if ( Hooks::isRegistered( 'ArticleAfterFetchContentObject' ) ) {
468  $contentObject = $this->mRevision->getContent(
470  $this->getContext()->getUser()
471  );
472 
473  $hookContentObject = $contentObject;
474 
475  // Avoid PHP 7.1 warning of passing $this by reference
476  $articlePage = $this;
477 
478  Hooks::run(
479  'ArticleAfterFetchContentObject',
480  [ &$articlePage, &$hookContentObject ],
481  '1.32'
482  );
483 
484  if ( $hookContentObject !== $contentObject ) {
485  // A hook handler is trying to override the content
486  $this->applyContentOverride( $hookContentObject );
487  }
488  }
489 
490  // For B/C only
491  $this->mContentObject = $this->mRevision->getContent(
493  $this->getContext()->getUser()
494  );
495 
496  return $this->mRevision->getRevisionRecord();
497  }
498 
505  private function makeFetchErrorContent() {
506  if ( !$this->fetchResult || $this->fetchResult->isOK() ) {
507  return null;
508  }
509 
510  return new MessageContent( $this->fetchResult->getMessage() );
511  }
512 
525  private function applyContentOverride( Content $override ) {
526  // Construct a fake revision
527  $rev = new MutableRevisionRecord( $this->getTitle() );
528  $rev->setContent( SlotRecord::MAIN, $override );
529 
530  $this->mRevision = new Revision( $rev );
531 
532  // For B/C only
533  $this->mContentObject = $override;
534  }
535 
541  public function isCurrent() {
542  # If no oldid, this is the current version.
543  if ( $this->getOldID() == 0 ) {
544  return true;
545  }
546 
547  return $this->mPage->exists() && $this->mRevision && $this->mRevision->isCurrent();
548  }
549 
559  public function getRevisionFetched() {
560  $this->fetchRevisionRecord();
561 
562  if ( $this->fetchResult->isOK() ) {
563  return $this->mRevision;
564  }
565  }
566 
575  public function getRevIdFetched() {
576  if ( $this->fetchResult && $this->fetchResult->isOK() ) {
577  return $this->fetchResult->value->getId();
578  } else {
579  return $this->mPage->getLatest();
580  }
581  }
582 
587  public function view() {
589 
590  # Get variables from query string
591  # As side effect this will load the revision and update the title
592  # in a revision ID is passed in the request, so this should remain
593  # the first call of this method even if $oldid is used way below.
594  $oldid = $this->getOldID();
595 
596  $user = $this->getContext()->getUser();
597  # Another whitelist check in case getOldID() is altering the title
598  $permErrors = $this->getTitle()->getUserPermissionsErrors( 'read', $user );
599  if ( count( $permErrors ) ) {
600  wfDebug( __METHOD__ . ": denied on secondary read check\n" );
601  throw new PermissionsError( 'read', $permErrors );
602  }
603 
604  $outputPage = $this->getContext()->getOutput();
605  # getOldID() may as well want us to redirect somewhere else
606  if ( $this->mRedirectUrl ) {
607  $outputPage->redirect( $this->mRedirectUrl );
608  wfDebug( __METHOD__ . ": redirecting due to oldid\n" );
609 
610  return;
611  }
612 
613  # If we got diff in the query, we want to see a diff page instead of the article.
614  if ( $this->getContext()->getRequest()->getCheck( 'diff' ) ) {
615  wfDebug( __METHOD__ . ": showing diff page\n" );
616  $this->showDiffPage();
617 
618  return;
619  }
620 
621  # Set page title (may be overridden by DISPLAYTITLE)
622  $outputPage->setPageTitle( $this->getTitle()->getPrefixedText() );
623 
624  $outputPage->setArticleFlag( true );
625  # Allow frames by default
626  $outputPage->allowClickjacking();
627 
628  $parserCache = MediaWikiServices::getInstance()->getParserCache();
629 
630  $parserOptions = $this->getParserOptions();
631  $poOptions = [];
632  # Render printable version, use printable version cache
633  if ( $outputPage->isPrintable() ) {
634  $parserOptions->setIsPrintable( true );
635  $poOptions['enableSectionEditLinks'] = false;
636  } elseif ( $this->disableSectionEditForRender
637  || !$this->isCurrent() || !$this->getTitle()->quickUserCan( 'edit', $user )
638  ) {
639  $poOptions['enableSectionEditLinks'] = false;
640  }
641 
642  # Try client and file cache
643  if ( !$wgDebugToolbar && $oldid === 0 && $this->mPage->checkTouched() ) {
644  # Try to stream the output from file cache
645  if ( $wgUseFileCache && $this->tryFileCache() ) {
646  wfDebug( __METHOD__ . ": done file cache\n" );
647  # tell wgOut that output is taken care of
648  $outputPage->disable();
649  $this->mPage->doViewUpdates( $user, $oldid );
650 
651  return;
652  }
653  }
654 
655  # Should the parser cache be used?
656  $useParserCache = $this->mPage->shouldCheckParserCache( $parserOptions, $oldid );
657  wfDebug( 'Article::view using parser cache: ' . ( $useParserCache ? 'yes' : 'no' ) . "\n" );
658  if ( $user->getStubThreshold() ) {
659  MediaWikiServices::getInstance()->getStatsdDataFactory()->increment( 'pcache_miss_stub' );
660  }
661 
662  $this->showRedirectedFromHeader();
663  $this->showNamespaceHeader();
664 
665  # Iterate through the possible ways of constructing the output text.
666  # Keep going until $outputDone is set, or we run out of things to do.
667  $pass = 0;
668  $outputDone = false;
669  $this->mParserOutput = false;
670 
671  while ( !$outputDone && ++$pass ) {
672  switch ( $pass ) {
673  case 1:
674  // Avoid PHP 7.1 warning of passing $this by reference
675  $articlePage = $this;
676  Hooks::run( 'ArticleViewHeader', [ &$articlePage, &$outputDone, &$useParserCache ] );
677  break;
678  case 2:
679  # Early abort if the page doesn't exist
680  if ( !$this->mPage->exists() ) {
681  wfDebug( __METHOD__ . ": showing missing article\n" );
682  $this->showMissingArticle();
683  $this->mPage->doViewUpdates( $user );
684  return;
685  }
686 
687  # Try the parser cache
688  if ( $useParserCache ) {
689  $this->mParserOutput = $parserCache->get( $this->mPage, $parserOptions );
690 
691  if ( $this->mParserOutput !== false ) {
692  if ( $oldid ) {
693  wfDebug( __METHOD__ . ": showing parser cache contents for current rev permalink\n" );
694  $this->setOldSubtitle( $oldid );
695  } else {
696  wfDebug( __METHOD__ . ": showing parser cache contents\n" );
697  }
698  $outputPage->addParserOutput( $this->mParserOutput, $poOptions );
699  # Ensure that UI elements requiring revision ID have
700  # the correct version information.
701  $outputPage->setRevisionId( $this->mPage->getLatest() );
702  # Preload timestamp to avoid a DB hit
703  $cachedTimestamp = $this->mParserOutput->getTimestamp();
704  if ( $cachedTimestamp !== null ) {
705  $outputPage->setRevisionTimestamp( $cachedTimestamp );
706  $this->mPage->setTimestamp( $cachedTimestamp );
707  }
708  $outputDone = true;
709  }
710  }
711  break;
712  case 3:
713  # Are we looking at an old revision
714  $rev = $this->fetchRevisionRecord();
715  if ( $oldid && $this->fetchResult->isOK() ) {
716  $this->setOldSubtitle( $oldid );
717 
718  if ( !$this->showDeletedRevisionHeader() ) {
719  wfDebug( __METHOD__ . ": cannot view deleted revision\n" );
720  return;
721  }
722  }
723 
724  # Ensure that UI elements requiring revision ID have
725  # the correct version information.
726  $outputPage->setRevisionId( $this->getRevIdFetched() );
727  # Preload timestamp to avoid a DB hit
728  $outputPage->setRevisionTimestamp( $this->mPage->getTimestamp() );
729 
730  # Pages containing custom CSS or JavaScript get special treatment
731  if ( $this->getTitle()->isSiteConfigPage() || $this->getTitle()->isUserConfigPage() ) {
732  $dir = $this->getContext()->getLanguage()->getDir();
733  $lang = $this->getContext()->getLanguage()->getHtmlCode();
734 
735  $outputPage->wrapWikiMsg(
736  "<div id='mw-clearyourcache' lang='$lang' dir='$dir' class='mw-content-$dir'>\n$1\n</div>",
737  'clearyourcache'
738  );
739  } elseif ( !Hooks::run( 'ArticleRevisionViewCustom', [
740  $rev,
741  $this->getTitle(),
742  $oldid,
743  $outputPage,
744  ] )
745  ) {
746  // NOTE: sync with hooks called in DifferenceEngine::renderNewRevision()
747  // Allow extensions do their own custom view for certain pages
748  $outputDone = true;
749  } elseif ( !Hooks::run( 'ArticleContentViewCustom',
750  [ $this->fetchContentObject(), $this->getTitle(), $outputPage ], '1.32' )
751  ) {
752  // NOTE: sync with hooks called in DifferenceEngine::renderNewRevision()
753  // Allow extensions do their own custom view for certain pages
754  $outputDone = true;
755  }
756  break;
757  case 4:
758  # Run the parse, protected by a pool counter
759  wfDebug( __METHOD__ . ": doing uncached parse\n" );
760 
761  $rev = $this->fetchRevisionRecord();
762  $error = null;
763 
764  if ( $rev ) {
765  $poolArticleView = new PoolWorkArticleView(
766  $this->getPage(),
767  $parserOptions,
768  $this->getRevIdFetched(),
769  $useParserCache,
770  $rev,
771  // permission checking was done earlier via showDeletedRevisionHeader()
772  RevisionRecord::RAW
773  );
774  $ok = $poolArticleView->execute();
775  $error = $poolArticleView->getError();
776  $this->mParserOutput = $poolArticleView->getParserOutput() ?: null;
777 
778  # Don't cache a dirty ParserOutput object
779  if ( $poolArticleView->getIsDirty() ) {
780  $outputPage->setCdnMaxage( 0 );
781  $outputPage->addHTML( "<!-- parser cache is expired, " .
782  "sending anyway due to pool overload-->\n" );
783  }
784  } else {
785  $ok = false;
786  }
787 
788  if ( !$ok ) {
789  if ( $error ) {
790  $outputPage->clearHTML(); // for release() errors
791  $outputPage->enableClientCache( false );
792  $outputPage->setRobotPolicy( 'noindex,nofollow' );
793 
794  $errortext = $error->getWikiText( false, 'view-pool-error' );
795  $outputPage->addWikiText( Html::errorBox( $errortext ) );
796  }
797  # Connection or timeout error
798  return;
799  }
800 
801  if ( $this->mParserOutput ) {
802  $outputPage->addParserOutput( $this->mParserOutput, $poOptions );
803  }
804 
805  if ( $rev && $this->getRevisionRedirectTarget( $rev ) ) {
806  $outputPage->addSubtitle( "<span id=\"redirectsub\">" .
807  $this->getContext()->msg( 'redirectpagesub' )->parse() . "</span>" );
808  }
809 
810  $outputDone = true;
811  break;
812  # Should be unreachable, but just in case...
813  default:
814  break 2;
815  }
816  }
817 
818  // Get the ParserOutput actually *displayed* here.
819  // Note that $this->mParserOutput is the *current*/oldid version output.
820  // Note that the ArticleViewHeader hook is allowed to set $outputDone to a
821  // ParserOutput instance.
822  $pOutput = ( $outputDone instanceof ParserOutput )
823  // phpcs:ignore MediaWiki.Usage.NestedInlineTernary.UnparenthesizedTernary -- FIXME T203805
824  ? $outputDone // object fetched by hook
825  : $this->mParserOutput ?: null; // ParserOutput or null, avoid false
826 
827  # Adjust title for main page & pages with displaytitle
828  if ( $pOutput ) {
829  $this->adjustDisplayTitle( $pOutput );
830  }
831 
832  # For the main page, overwrite the <title> element with the con-
833  # tents of 'pagetitle-view-mainpage' instead of the default (if
834  # that's not empty).
835  # This message always exists because it is in the i18n files
836  if ( $this->getTitle()->isMainPage() ) {
837  $msg = wfMessage( 'pagetitle-view-mainpage' )->inContentLanguage();
838  if ( !$msg->isDisabled() ) {
839  $outputPage->setHTMLTitle( $msg->title( $this->getTitle() )->text() );
840  }
841  }
842 
843  # Use adaptive TTLs for CDN so delayed/failed purges are noticed less often.
844  # This could use getTouched(), but that could be scary for major template edits.
845  $outputPage->adaptCdnTTL( $this->mPage->getTimestamp(), IExpiringStore::TTL_DAY );
846 
847  # Check for any __NOINDEX__ tags on the page using $pOutput
848  $policy = $this->getRobotPolicy( 'view', $pOutput ?: null );
849  $outputPage->setIndexPolicy( $policy['index'] );
850  $outputPage->setFollowPolicy( $policy['follow'] ); // FIXME: test this
851 
852  $this->showViewFooter();
853  $this->mPage->doViewUpdates( $user, $oldid ); // FIXME: test this
854 
855  # Load the postEdit module if the user just saved this revision
856  # See also EditPage::setPostEditCookie
857  $request = $this->getContext()->getRequest();
859  $postEdit = $request->getCookie( $cookieKey );
860  if ( $postEdit ) {
861  # Clear the cookie. This also prevents caching of the response.
862  $request->response()->clearCookie( $cookieKey );
863  $outputPage->addJsConfigVars( 'wgPostEdit', $postEdit );
864  $outputPage->addModules( 'mediawiki.action.view.postEdit' ); // FIXME: test this
865  }
866  }
867 
872  private function getRevisionRedirectTarget( RevisionRecord $revision ) {
873  // TODO: find a *good* place for the code that determines the redirect target for
874  // a given revision!
875  // NOTE: Use main slot content. Compare code in DerivedPageDataUpdater::revisionIsRedirect.
876  $content = $revision->getContent( SlotRecord::MAIN );
877  return $content ? $content->getRedirectTarget() : null;
878  }
879 
884  public function adjustDisplayTitle( ParserOutput $pOutput ) {
885  $out = $this->getContext()->getOutput();
886 
887  # Adjust the title if it was set by displaytitle, -{T|}- or language conversion
888  $titleText = $pOutput->getTitleText();
889  if ( strval( $titleText ) !== '' ) {
890  $out->setPageTitle( $titleText );
891  $out->setDisplayTitle( $titleText );
892  }
893  }
894 
899  protected function showDiffPage() {
900  $request = $this->getContext()->getRequest();
901  $user = $this->getContext()->getUser();
902  $diff = $request->getVal( 'diff' );
903  $rcid = $request->getVal( 'rcid' );
904  $diffOnly = $request->getBool( 'diffonly', $user->getOption( 'diffonly' ) );
905  $purge = $request->getVal( 'action' ) == 'purge';
906  $unhide = $request->getInt( 'unhide' ) == 1;
907  $oldid = $this->getOldID();
908 
909  $rev = $this->getRevisionFetched();
910 
911  if ( !$rev ) {
912  $this->getContext()->getOutput()->setPageTitle( wfMessage( 'errorpagetitle' ) );
913  $msg = $this->getContext()->msg( 'difference-missing-revision' )
914  ->params( $oldid )
915  ->numParams( 1 )
916  ->parseAsBlock();
917  $this->getContext()->getOutput()->addHTML( $msg );
918  return;
919  }
920 
921  $contentHandler = $rev->getContentHandler();
922  $de = $contentHandler->createDifferenceEngine(
923  $this->getContext(),
924  $oldid,
925  $diff,
926  $rcid,
927  $purge,
928  $unhide
929  );
930 
931  // DifferenceEngine directly fetched the revision:
932  $this->mRevIdFetched = $de->getNewid();
933  $de->showDiffPage( $diffOnly );
934 
935  // Run view updates for the newer revision being diffed (and shown
936  // below the diff if not $diffOnly).
937  list( $old, $new ) = $de->mapDiffPrevNext( $oldid, $diff );
938  // New can be false, convert it to 0 - this conveniently means the latest revision
939  $this->mPage->doViewUpdates( $user, (int)$new );
940  }
941 
949  public function getRobotPolicy( $action, ParserOutput $pOutput = null ) {
951 
952  $ns = $this->getTitle()->getNamespace();
953 
954  # Don't index user and user talk pages for blocked users (T13443)
955  if ( ( $ns == NS_USER || $ns == NS_USER_TALK ) && !$this->getTitle()->isSubpage() ) {
956  $specificTarget = null;
957  $vagueTarget = null;
958  $titleText = $this->getTitle()->getText();
959  if ( IP::isValid( $titleText ) ) {
960  $vagueTarget = $titleText;
961  } else {
962  $specificTarget = $titleText;
963  }
964  if ( Block::newFromTarget( $specificTarget, $vagueTarget ) instanceof Block ) {
965  return [
966  'index' => 'noindex',
967  'follow' => 'nofollow'
968  ];
969  }
970  }
971 
972  if ( $this->mPage->getId() === 0 || $this->getOldID() ) {
973  # Non-articles (special pages etc), and old revisions
974  return [
975  'index' => 'noindex',
976  'follow' => 'nofollow'
977  ];
978  } elseif ( $this->getContext()->getOutput()->isPrintable() ) {
979  # Discourage indexing of printable versions, but encourage following
980  return [
981  'index' => 'noindex',
982  'follow' => 'follow'
983  ];
984  } elseif ( $this->getContext()->getRequest()->getInt( 'curid' ) ) {
985  # For ?curid=x urls, disallow indexing
986  return [
987  'index' => 'noindex',
988  'follow' => 'follow'
989  ];
990  }
991 
992  # Otherwise, construct the policy based on the various config variables.
994 
995  if ( isset( $wgNamespaceRobotPolicies[$ns] ) ) {
996  # Honour customised robot policies for this namespace
997  $policy = array_merge(
998  $policy,
999  self::formatRobotPolicy( $wgNamespaceRobotPolicies[$ns] )
1000  );
1001  }
1002  if ( $this->getTitle()->canUseNoindex() && is_object( $pOutput ) && $pOutput->getIndexPolicy() ) {
1003  # __INDEX__ and __NOINDEX__ magic words, if allowed. Incorporates
1004  # a final sanity check that we have really got the parser output.
1005  $policy = array_merge(
1006  $policy,
1007  [ 'index' => $pOutput->getIndexPolicy() ]
1008  );
1009  }
1010 
1011  if ( isset( $wgArticleRobotPolicies[$this->getTitle()->getPrefixedText()] ) ) {
1012  # (T16900) site config can override user-defined __INDEX__ or __NOINDEX__
1013  $policy = array_merge(
1014  $policy,
1015  self::formatRobotPolicy( $wgArticleRobotPolicies[$this->getTitle()->getPrefixedText()] )
1016  );
1017  }
1018 
1019  return $policy;
1020  }
1021 
1029  public static function formatRobotPolicy( $policy ) {
1030  if ( is_array( $policy ) ) {
1031  return $policy;
1032  } elseif ( !$policy ) {
1033  return [];
1034  }
1035 
1036  $policy = explode( ',', $policy );
1037  $policy = array_map( 'trim', $policy );
1038 
1039  $arr = [];
1040  foreach ( $policy as $var ) {
1041  if ( in_array( $var, [ 'index', 'noindex' ] ) ) {
1042  $arr['index'] = $var;
1043  } elseif ( in_array( $var, [ 'follow', 'nofollow' ] ) ) {
1044  $arr['follow'] = $var;
1045  }
1046  }
1047 
1048  return $arr;
1049  }
1050 
1058  public function showRedirectedFromHeader() {
1059  global $wgRedirectSources;
1060 
1061  $context = $this->getContext();
1062  $outputPage = $context->getOutput();
1063  $request = $context->getRequest();
1064  $rdfrom = $request->getVal( 'rdfrom' );
1065 
1066  // Construct a URL for the current page view, but with the target title
1067  $query = $request->getValues();
1068  unset( $query['rdfrom'] );
1069  unset( $query['title'] );
1070  if ( $this->getTitle()->isRedirect() ) {
1071  // Prevent double redirects
1072  $query['redirect'] = 'no';
1073  }
1074  $redirectTargetUrl = $this->getTitle()->getLinkURL( $query );
1075 
1076  if ( isset( $this->mRedirectedFrom ) ) {
1077  // Avoid PHP 7.1 warning of passing $this by reference
1078  $articlePage = $this;
1079 
1080  // This is an internally redirected page view.
1081  // We'll need a backlink to the source page for navigation.
1082  if ( Hooks::run( 'ArticleViewRedirect', [ &$articlePage ] ) ) {
1083  $redir = Linker::linkKnown(
1084  $this->mRedirectedFrom,
1085  null,
1086  [],
1087  [ 'redirect' => 'no' ]
1088  );
1089 
1090  $outputPage->addSubtitle( "<span class=\"mw-redirectedfrom\">" .
1091  $context->msg( 'redirectedfrom' )->rawParams( $redir )->parse()
1092  . "</span>" );
1093 
1094  // Add the script to update the displayed URL and
1095  // set the fragment if one was specified in the redirect
1096  $outputPage->addJsConfigVars( [
1097  'wgInternalRedirectTargetUrl' => $redirectTargetUrl,
1098  ] );
1099  $outputPage->addModules( 'mediawiki.action.view.redirect' );
1100 
1101  // Add a <link rel="canonical"> tag
1102  $outputPage->setCanonicalUrl( $this->getTitle()->getCanonicalURL() );
1103 
1104  // Tell the output object that the user arrived at this article through a redirect
1105  $outputPage->setRedirectedFrom( $this->mRedirectedFrom );
1106 
1107  return true;
1108  }
1109  } elseif ( $rdfrom ) {
1110  // This is an externally redirected view, from some other wiki.
1111  // If it was reported from a trusted site, supply a backlink.
1112  if ( $wgRedirectSources && preg_match( $wgRedirectSources, $rdfrom ) ) {
1113  $redir = Linker::makeExternalLink( $rdfrom, $rdfrom );
1114  $outputPage->addSubtitle( "<span class=\"mw-redirectedfrom\">" .
1115  $context->msg( 'redirectedfrom' )->rawParams( $redir )->parse()
1116  . "</span>" );
1117 
1118  // Add the script to update the displayed URL
1119  $outputPage->addJsConfigVars( [
1120  'wgInternalRedirectTargetUrl' => $redirectTargetUrl,
1121  ] );
1122  $outputPage->addModules( 'mediawiki.action.view.redirect' );
1123 
1124  return true;
1125  }
1126  }
1127 
1128  return false;
1129  }
1130 
1135  public function showNamespaceHeader() {
1136  if ( $this->getTitle()->isTalkPage() ) {
1137  if ( !wfMessage( 'talkpageheader' )->isDisabled() ) {
1138  $this->getContext()->getOutput()->wrapWikiMsg(
1139  "<div class=\"mw-talkpageheader\">\n$1\n</div>",
1140  [ 'talkpageheader' ]
1141  );
1142  }
1143  }
1144  }
1145 
1149  public function showViewFooter() {
1150  # check if we're displaying a [[User talk:x.x.x.x]] anonymous talk page
1151  if ( $this->getTitle()->getNamespace() == NS_USER_TALK
1152  && IP::isValid( $this->getTitle()->getText() )
1153  ) {
1154  $this->getContext()->getOutput()->addWikiMsg( 'anontalkpagetext' );
1155  }
1156 
1157  // Show a footer allowing the user to patrol the shown revision or page if possible
1158  $patrolFooterShown = $this->showPatrolFooter();
1159 
1160  Hooks::run( 'ArticleViewFooter', [ $this, $patrolFooterShown ] );
1161  }
1162 
1172  public function showPatrolFooter() {
1174 
1175  // Allow hooks to decide whether to not output this at all
1176  if ( !Hooks::run( 'ArticleShowPatrolFooter', [ $this ] ) ) {
1177  return false;
1178  }
1179 
1180  $outputPage = $this->getContext()->getOutput();
1181  $user = $this->getContext()->getUser();
1182  $title = $this->getTitle();
1183  $rc = false;
1184 
1185  if ( !$title->quickUserCan( 'patrol', $user )
1187  || ( $wgUseFilePatrol && $title->inNamespace( NS_FILE ) ) )
1188  ) {
1189  // Patrolling is disabled or the user isn't allowed to
1190  return false;
1191  }
1192 
1193  if ( $this->mRevision
1194  && !RecentChange::isInRCLifespan( $this->mRevision->getTimestamp(), 21600 )
1195  ) {
1196  // The current revision is already older than what could be in the RC table
1197  // 6h tolerance because the RC might not be cleaned out regularly
1198  return false;
1199  }
1200 
1201  // Check for cached results
1202  $cache = MediaWikiServices::getInstance()->getMainWANObjectCache();
1203  $key = $cache->makeKey( 'unpatrollable-page', $title->getArticleID() );
1204  if ( $cache->get( $key ) ) {
1205  return false;
1206  }
1207 
1208  $dbr = wfGetDB( DB_REPLICA );
1209  $oldestRevisionTimestamp = $dbr->selectField(
1210  'revision',
1211  'MIN( rev_timestamp )',
1212  [ 'rev_page' => $title->getArticleID() ],
1213  __METHOD__
1214  );
1215 
1216  // New page patrol: Get the timestamp of the oldest revison which
1217  // the revision table holds for the given page. Then we look
1218  // whether it's within the RC lifespan and if it is, we try
1219  // to get the recentchanges row belonging to that entry
1220  // (with rc_new = 1).
1221  $recentPageCreation = false;
1222  if ( $oldestRevisionTimestamp
1223  && RecentChange::isInRCLifespan( $oldestRevisionTimestamp, 21600 )
1224  ) {
1225  // 6h tolerance because the RC might not be cleaned out regularly
1226  $recentPageCreation = true;
1228  [
1229  'rc_new' => 1,
1230  'rc_timestamp' => $oldestRevisionTimestamp,
1231  'rc_namespace' => $title->getNamespace(),
1232  'rc_cur_id' => $title->getArticleID()
1233  ],
1234  __METHOD__
1235  );
1236  if ( $rc ) {
1237  // Use generic patrol message for new pages
1238  $markPatrolledMsg = wfMessage( 'markaspatrolledtext' );
1239  }
1240  }
1241 
1242  // File patrol: Get the timestamp of the latest upload for this page,
1243  // check whether it is within the RC lifespan and if it is, we try
1244  // to get the recentchanges row belonging to that entry
1245  // (with rc_type = RC_LOG, rc_log_type = upload).
1246  $recentFileUpload = false;
1247  if ( ( !$rc || $rc->getAttribute( 'rc_patrolled' ) ) && $wgUseFilePatrol
1248  && $title->getNamespace() === NS_FILE ) {
1249  // Retrieve timestamp of most recent upload
1250  $newestUploadTimestamp = $dbr->selectField(
1251  'image',
1252  'MAX( img_timestamp )',
1253  [ 'img_name' => $title->getDBkey() ],
1254  __METHOD__
1255  );
1256  if ( $newestUploadTimestamp
1257  && RecentChange::isInRCLifespan( $newestUploadTimestamp, 21600 )
1258  ) {
1259  // 6h tolerance because the RC might not be cleaned out regularly
1260  $recentFileUpload = true;
1262  [
1263  'rc_type' => RC_LOG,
1264  'rc_log_type' => 'upload',
1265  'rc_timestamp' => $newestUploadTimestamp,
1266  'rc_namespace' => NS_FILE,
1267  'rc_cur_id' => $title->getArticleID()
1268  ],
1269  __METHOD__
1270  );
1271  if ( $rc ) {
1272  // Use patrol message specific to files
1273  $markPatrolledMsg = wfMessage( 'markaspatrolledtext-file' );
1274  }
1275  }
1276  }
1277 
1278  if ( !$recentPageCreation && !$recentFileUpload ) {
1279  // Page creation and latest upload (for files) is too old to be in RC
1280 
1281  // We definitely can't patrol so cache the information
1282  // When a new file version is uploaded, the cache is cleared
1283  $cache->set( $key, '1' );
1284 
1285  return false;
1286  }
1287 
1288  if ( !$rc ) {
1289  // Don't cache: This can be hit if the page gets accessed very fast after
1290  // its creation / latest upload or in case we have high replica DB lag. In case
1291  // the revision is too old, we will already return above.
1292  return false;
1293  }
1294 
1295  if ( $rc->getAttribute( 'rc_patrolled' ) ) {
1296  // Patrolled RC entry around
1297 
1298  // Cache the information we gathered above in case we can't patrol
1299  // Don't cache in case we can patrol as this could change
1300  $cache->set( $key, '1' );
1301 
1302  return false;
1303  }
1304 
1305  if ( $rc->getPerformer()->equals( $user ) ) {
1306  // Don't show a patrol link for own creations/uploads. If the user could
1307  // patrol them, they already would be patrolled
1308  return false;
1309  }
1310 
1311  $outputPage->preventClickjacking();
1312  if ( $user->isAllowed( 'writeapi' ) ) {
1313  $outputPage->addModules( 'mediawiki.page.patrol.ajax' );
1314  }
1315 
1317  $title,
1318  $markPatrolledMsg->escaped(),
1319  [],
1320  [
1321  'action' => 'markpatrolled',
1322  'rcid' => $rc->getAttribute( 'rc_id' ),
1323  ]
1324  );
1325 
1326  $outputPage->addHTML(
1327  "<div class='patrollink' data-mw='interface'>" .
1328  wfMessage( 'markaspatrolledlink' )->rawParams( $link )->escaped() .
1329  '</div>'
1330  );
1331 
1332  return true;
1333  }
1334 
1341  public static function purgePatrolFooterCache( $articleID ) {
1342  $cache = MediaWikiServices::getInstance()->getMainWANObjectCache();
1343  $cache->delete( $cache->makeKey( 'unpatrollable-page', $articleID ) );
1344  }
1345 
1350  public function showMissingArticle() {
1351  global $wgSend404Code;
1352 
1353  $outputPage = $this->getContext()->getOutput();
1354  // Whether the page is a root user page of an existing user (but not a subpage)
1355  $validUserPage = false;
1356 
1357  $title = $this->getTitle();
1358 
1359  # Show info in user (talk) namespace. Does the user exist? Is he blocked?
1360  if ( $title->getNamespace() == NS_USER
1361  || $title->getNamespace() == NS_USER_TALK
1362  ) {
1363  $rootPart = explode( '/', $title->getText() )[0];
1364  $user = User::newFromName( $rootPart, false /* allow IP users */ );
1365  $ip = User::isIP( $rootPart );
1366  $block = Block::newFromTarget( $user, $user );
1367 
1368  if ( !( $user && $user->isLoggedIn() ) && !$ip ) { # User does not exist
1369  $outputPage->wrapWikiMsg( "<div class=\"mw-userpage-userdoesnotexist error\">\n\$1\n</div>",
1370  [ 'userpage-userdoesnotexist-view', wfEscapeWikiText( $rootPart ) ] );
1371  } elseif ( !is_null( $block ) && $block->getType() != Block::TYPE_AUTO ) {
1372  # Show log extract if the user is currently blocked
1374  $outputPage,
1375  'block',
1376  MWNamespace::getCanonicalName( NS_USER ) . ':' . $block->getTarget(),
1377  '',
1378  [
1379  'lim' => 1,
1380  'showIfEmpty' => false,
1381  'msgKey' => [
1382  'blocked-notice-logextract',
1383  $user->getName() # Support GENDER in notice
1384  ]
1385  ]
1386  );
1387  $validUserPage = !$title->isSubpage();
1388  } else {
1389  $validUserPage = !$title->isSubpage();
1390  }
1391  }
1392 
1393  Hooks::run( 'ShowMissingArticle', [ $this ] );
1394 
1395  # Show delete and move logs if there were any such events.
1396  # The logging query can DOS the site when bots/crawlers cause 404 floods,
1397  # so be careful showing this. 404 pages must be cheap as they are hard to cache.
1398  $cache = MediaWikiServices::getInstance()->getMainObjectStash();
1399  $key = $cache->makeKey( 'page-recent-delete', md5( $title->getPrefixedText() ) );
1400  $loggedIn = $this->getContext()->getUser()->isLoggedIn();
1401  $sessionExists = $this->getContext()->getRequest()->getSession()->isPersistent();
1402  if ( $loggedIn || $cache->get( $key ) || $sessionExists ) {
1403  $logTypes = [ 'delete', 'move', 'protect' ];
1404 
1405  $dbr = wfGetDB( DB_REPLICA );
1406 
1407  $conds = [ 'log_action != ' . $dbr->addQuotes( 'revision' ) ];
1408  // Give extensions a chance to hide their (unrelated) log entries
1409  Hooks::run( 'Article::MissingArticleConditions', [ &$conds, $logTypes ] );
1411  $outputPage,
1412  $logTypes,
1413  $title,
1414  '',
1415  [
1416  'lim' => 10,
1417  'conds' => $conds,
1418  'showIfEmpty' => false,
1419  'msgKey' => [ $loggedIn || $sessionExists
1420  ? 'moveddeleted-notice'
1421  : 'moveddeleted-notice-recent'
1422  ]
1423  ]
1424  );
1425  }
1426 
1427  if ( !$this->mPage->hasViewableContent() && $wgSend404Code && !$validUserPage ) {
1428  // If there's no backing content, send a 404 Not Found
1429  // for better machine handling of broken links.
1430  $this->getContext()->getRequest()->response()->statusHeader( 404 );
1431  }
1432 
1433  // Also apply the robot policy for nonexisting pages (even if a 404 was used for sanity)
1434  $policy = $this->getRobotPolicy( 'view' );
1435  $outputPage->setIndexPolicy( $policy['index'] );
1436  $outputPage->setFollowPolicy( $policy['follow'] );
1437 
1438  $hookResult = Hooks::run( 'BeforeDisplayNoArticleText', [ $this ] );
1439 
1440  if ( !$hookResult ) {
1441  return;
1442  }
1443 
1444  # Show error message
1445  $oldid = $this->getOldID();
1446  if ( !$oldid && $title->getNamespace() === NS_MEDIAWIKI && $title->hasSourceText() ) {
1447  // use fake Content object for system message
1448  $parserOptions = ParserOptions::newCanonical( 'canonical' );
1449  $outputPage->addParserOutput( $this->getEmptyPageParserOutput( $parserOptions ) );
1450  } else {
1451  if ( $oldid ) {
1452  $text = wfMessage( 'missing-revision', $oldid )->plain();
1453  } elseif ( $title->quickUserCan( 'create', $this->getContext()->getUser() )
1454  && $title->quickUserCan( 'edit', $this->getContext()->getUser() )
1455  ) {
1456  $message = $this->getContext()->getUser()->isLoggedIn() ? 'noarticletext' : 'noarticletextanon';
1457  $text = wfMessage( $message )->plain();
1458  } else {
1459  $text = wfMessage( 'noarticletext-nopermission' )->plain();
1460  }
1461 
1462  $dir = $this->getContext()->getLanguage()->getDir();
1463  $lang = $this->getContext()->getLanguage()->getHtmlCode();
1464  $outputPage->addWikiText( Xml::openElement( 'div', [
1465  'class' => "noarticletext mw-content-$dir",
1466  'dir' => $dir,
1467  'lang' => $lang,
1468  ] ) . "\n$text\n</div>" );
1469  }
1470  }
1471 
1478  public function showDeletedRevisionHeader() {
1479  if ( !$this->mRevision->isDeleted( Revision::DELETED_TEXT ) ) {
1480  // Not deleted
1481  return true;
1482  }
1483 
1484  $outputPage = $this->getContext()->getOutput();
1485  $user = $this->getContext()->getUser();
1486  // If the user is not allowed to see it...
1487  if ( !$this->mRevision->userCan( Revision::DELETED_TEXT, $user ) ) {
1488  $outputPage->wrapWikiMsg( "<div class='mw-warning plainlinks'>\n$1\n</div>\n",
1489  'rev-deleted-text-permission' );
1490 
1491  return false;
1492  // If the user needs to confirm that they want to see it...
1493  } elseif ( $this->getContext()->getRequest()->getInt( 'unhide' ) != 1 ) {
1494  # Give explanation and add a link to view the revision...
1495  $oldid = intval( $this->getOldID() );
1496  $link = $this->getTitle()->getFullURL( "oldid={$oldid}&unhide=1" );
1497  $msg = $this->mRevision->isDeleted( Revision::DELETED_RESTRICTED ) ?
1498  'rev-suppressed-text-unhide' : 'rev-deleted-text-unhide';
1499  $outputPage->wrapWikiMsg( "<div class='mw-warning plainlinks'>\n$1\n</div>\n",
1500  [ $msg, $link ] );
1501 
1502  return false;
1503  // We are allowed to see...
1504  } else {
1505  $msg = $this->mRevision->isDeleted( Revision::DELETED_RESTRICTED ) ?
1506  'rev-suppressed-text-view' : 'rev-deleted-text-view';
1507  $outputPage->wrapWikiMsg( "<div class='mw-warning plainlinks'>\n$1\n</div>\n", $msg );
1508 
1509  return true;
1510  }
1511  }
1512 
1521  public function setOldSubtitle( $oldid = 0 ) {
1522  // Avoid PHP 7.1 warning of passing $this by reference
1523  $articlePage = $this;
1524 
1525  if ( !Hooks::run( 'DisplayOldSubtitle', [ &$articlePage, &$oldid ] ) ) {
1526  return;
1527  }
1528 
1529  $context = $this->getContext();
1530  $unhide = $context->getRequest()->getInt( 'unhide' ) == 1;
1531 
1532  # Cascade unhide param in links for easy deletion browsing
1533  $extraParams = [];
1534  if ( $unhide ) {
1535  $extraParams['unhide'] = 1;
1536  }
1537 
1538  if ( $this->mRevision && $this->mRevision->getId() === $oldid ) {
1539  $revision = $this->mRevision;
1540  } else {
1541  $revision = Revision::newFromId( $oldid );
1542  }
1543 
1544  $timestamp = $revision->getTimestamp();
1545 
1546  $current = ( $oldid == $this->mPage->getLatest() );
1547  $language = $context->getLanguage();
1548  $user = $context->getUser();
1549 
1550  $td = $language->userTimeAndDate( $timestamp, $user );
1551  $tddate = $language->userDate( $timestamp, $user );
1552  $tdtime = $language->userTime( $timestamp, $user );
1553 
1554  # Show user links if allowed to see them. If hidden, then show them only if requested...
1555  $userlinks = Linker::revUserTools( $revision, !$unhide );
1556 
1557  $infomsg = $current && !$context->msg( 'revision-info-current' )->isDisabled()
1558  ? 'revision-info-current'
1559  : 'revision-info';
1560 
1561  $outputPage = $context->getOutput();
1562  $revisionInfo = "<div id=\"mw-{$infomsg}\">" .
1563  $context->msg( $infomsg, $td )
1564  ->rawParams( $userlinks )
1565  ->params( $revision->getId(), $tddate, $tdtime, $revision->getUserText() )
1566  ->rawParams( Linker::revComment( $revision, true, true ) )
1567  ->parse() .
1568  "</div>";
1569 
1570  $lnk = $current
1571  ? $context->msg( 'currentrevisionlink' )->escaped()
1573  $this->getTitle(),
1574  $context->msg( 'currentrevisionlink' )->escaped(),
1575  [],
1576  $extraParams
1577  );
1578  $curdiff = $current
1579  ? $context->msg( 'diff' )->escaped()
1581  $this->getTitle(),
1582  $context->msg( 'diff' )->escaped(),
1583  [],
1584  [
1585  'diff' => 'cur',
1586  'oldid' => $oldid
1587  ] + $extraParams
1588  );
1589  $prev = $this->getTitle()->getPreviousRevisionID( $oldid );
1590  $prevlink = $prev
1592  $this->getTitle(),
1593  $context->msg( 'previousrevision' )->escaped(),
1594  [],
1595  [
1596  'direction' => 'prev',
1597  'oldid' => $oldid
1598  ] + $extraParams
1599  )
1600  : $context->msg( 'previousrevision' )->escaped();
1601  $prevdiff = $prev
1603  $this->getTitle(),
1604  $context->msg( 'diff' )->escaped(),
1605  [],
1606  [
1607  'diff' => 'prev',
1608  'oldid' => $oldid
1609  ] + $extraParams
1610  )
1611  : $context->msg( 'diff' )->escaped();
1612  $nextlink = $current
1613  ? $context->msg( 'nextrevision' )->escaped()
1615  $this->getTitle(),
1616  $context->msg( 'nextrevision' )->escaped(),
1617  [],
1618  [
1619  'direction' => 'next',
1620  'oldid' => $oldid
1621  ] + $extraParams
1622  );
1623  $nextdiff = $current
1624  ? $context->msg( 'diff' )->escaped()
1626  $this->getTitle(),
1627  $context->msg( 'diff' )->escaped(),
1628  [],
1629  [
1630  'diff' => 'next',
1631  'oldid' => $oldid
1632  ] + $extraParams
1633  );
1634 
1635  $cdel = Linker::getRevDeleteLink( $user, $revision, $this->getTitle() );
1636  if ( $cdel !== '' ) {
1637  $cdel .= ' ';
1638  }
1639 
1640  // the outer div is need for styling the revision info and nav in MobileFrontend
1641  $outputPage->addSubtitle( "<div class=\"mw-revision\">" . $revisionInfo .
1642  "<div id=\"mw-revision-nav\">" . $cdel .
1643  $context->msg( 'revision-nav' )->rawParams(
1644  $prevdiff, $prevlink, $lnk, $curdiff, $nextlink, $nextdiff
1645  )->escaped() . "</div></div>" );
1646  }
1647 
1661  public function viewRedirect( $target, $appendSubtitle = true, $forceKnown = false ) {
1662  $lang = $this->getTitle()->getPageLanguage();
1663  $out = $this->getContext()->getOutput();
1664  if ( $appendSubtitle ) {
1665  $out->addSubtitle( wfMessage( 'redirectpagesub' ) );
1666  }
1667  $out->addModuleStyles( 'mediawiki.action.view.redirectPage' );
1668  return static::getRedirectHeaderHtml( $lang, $target, $forceKnown );
1669  }
1670 
1683  public static function getRedirectHeaderHtml( Language $lang, $target, $forceKnown = false ) {
1684  if ( !is_array( $target ) ) {
1685  $target = [ $target ];
1686  }
1687 
1688  $html = '<ul class="redirectText">';
1690  foreach ( $target as $title ) {
1691  $html .= '<li>' . Linker::link(
1692  $title,
1693  htmlspecialchars( $title->getFullText() ),
1694  [],
1695  // Make sure wiki page redirects are not followed
1696  $title->isRedirect() ? [ 'redirect' => 'no' ] : [],
1697  ( $forceKnown ? [ 'known', 'noclasses' ] : [] )
1698  ) . '</li>';
1699  }
1700  $html .= '</ul>';
1701 
1702  $redirectToText = wfMessage( 'redirectto' )->inLanguage( $lang )->escaped();
1703 
1704  return '<div class="redirectMsg">' .
1705  '<p>' . $redirectToText . '</p>' .
1706  $html .
1707  '</div>';
1708  }
1709 
1718  public function addHelpLink( $to, $overrideBaseUrl = false ) {
1719  $msg = wfMessage(
1720  'namespace-' . $this->getTitle()->getNamespace() . '-helppage'
1721  );
1722 
1723  $out = $this->getContext()->getOutput();
1724  if ( !$msg->isDisabled() ) {
1725  $helpUrl = Skin::makeUrl( $msg->plain() );
1726  $out->addHelpLink( $helpUrl, true );
1727  } else {
1728  $out->addHelpLink( $to, $overrideBaseUrl );
1729  }
1730  }
1731 
1735  public function render() {
1736  $this->getContext()->getRequest()->response()->header( 'X-Robots-Tag: noindex' );
1737  $this->getContext()->getOutput()->setArticleBodyOnly( true );
1738  $this->disableSectionEditForRender = true;
1739  $this->view();
1740  }
1741 
1745  public function protect() {
1746  $form = new ProtectionForm( $this );
1747  $form->execute();
1748  }
1749 
1753  public function unprotect() {
1754  $this->protect();
1755  }
1756 
1760  public function delete() {
1761  # This code desperately needs to be totally rewritten
1762 
1763  $title = $this->getTitle();
1764  $context = $this->getContext();
1765  $user = $context->getUser();
1766  $request = $context->getRequest();
1767 
1768  # Check permissions
1769  $permissionErrors = $title->getUserPermissionsErrors( 'delete', $user );
1770  if ( count( $permissionErrors ) ) {
1771  throw new PermissionsError( 'delete', $permissionErrors );
1772  }
1773 
1774  # Read-only check...
1775  if ( wfReadOnly() ) {
1776  throw new ReadOnlyError;
1777  }
1778 
1779  # Better double-check that it hasn't been deleted yet!
1780  $this->mPage->loadPageData(
1781  $request->wasPosted() ? WikiPage::READ_LATEST : WikiPage::READ_NORMAL
1782  );
1783  if ( !$this->mPage->exists() ) {
1784  $deleteLogPage = new LogPage( 'delete' );
1785  $outputPage = $context->getOutput();
1786  $outputPage->setPageTitle( $context->msg( 'cannotdelete-title', $title->getPrefixedText() ) );
1787  $outputPage->wrapWikiMsg( "<div class=\"error mw-error-cannotdelete\">\n$1\n</div>",
1788  [ 'cannotdelete', wfEscapeWikiText( $title->getPrefixedText() ) ]
1789  );
1790  $outputPage->addHTML(
1791  Xml::element( 'h2', null, $deleteLogPage->getName()->text() )
1792  );
1794  $outputPage,
1795  'delete',
1796  $title
1797  );
1798 
1799  return;
1800  }
1801 
1802  $deleteReasonList = $request->getText( 'wpDeleteReasonList', 'other' );
1803  $deleteReason = $request->getText( 'wpReason' );
1804 
1805  if ( $deleteReasonList == 'other' ) {
1806  $reason = $deleteReason;
1807  } elseif ( $deleteReason != '' ) {
1808  // Entry from drop down menu + additional comment
1809  $colonseparator = wfMessage( 'colon-separator' )->inContentLanguage()->text();
1810  $reason = $deleteReasonList . $colonseparator . $deleteReason;
1811  } else {
1812  $reason = $deleteReasonList;
1813  }
1814 
1815  if ( $request->wasPosted() && $user->matchEditToken( $request->getVal( 'wpEditToken' ),
1816  [ 'delete', $this->getTitle()->getPrefixedText() ] )
1817  ) {
1818  # Flag to hide all contents of the archived revisions
1819  $suppress = $request->getCheck( 'wpSuppress' ) && $user->isAllowed( 'suppressrevision' );
1820 
1821  $this->doDelete( $reason, $suppress );
1822 
1823  WatchAction::doWatchOrUnwatch( $request->getCheck( 'wpWatch' ), $title, $user );
1824 
1825  return;
1826  }
1827 
1828  // Generate deletion reason
1829  $hasHistory = false;
1830  if ( !$reason ) {
1831  try {
1832  $reason = $this->generateReason( $hasHistory );
1833  } catch ( Exception $e ) {
1834  # if a page is horribly broken, we still want to be able to
1835  # delete it. So be lenient about errors here.
1836  wfDebug( "Error while building auto delete summary: $e" );
1837  $reason = '';
1838  }
1839  }
1840 
1841  // If the page has a history, insert a warning
1842  if ( $hasHistory ) {
1843  $title = $this->getTitle();
1844 
1845  // The following can use the real revision count as this is only being shown for users
1846  // that can delete this page.
1847  // This, as a side-effect, also makes sure that the following query isn't being run for
1848  // pages with a larger history, unless the user has the 'bigdelete' right
1849  // (and is about to delete this page).
1850  $dbr = wfGetDB( DB_REPLICA );
1851  $revisions = $edits = (int)$dbr->selectField(
1852  'revision',
1853  'COUNT(rev_page)',
1854  [ 'rev_page' => $title->getArticleID() ],
1855  __METHOD__
1856  );
1857 
1858  // @todo i18n issue/patchwork message
1859  $context->getOutput()->addHTML(
1860  '<strong class="mw-delete-warning-revisions">' .
1861  $context->msg( 'historywarning' )->numParams( $revisions )->parse() .
1862  $context->msg( 'word-separator' )->escaped() . Linker::linkKnown( $title,
1863  $context->msg( 'history' )->escaped(),
1864  [],
1865  [ 'action' => 'history' ] ) .
1866  '</strong>'
1867  );
1868 
1869  if ( $title->isBigDeletion() ) {
1870  global $wgDeleteRevisionsLimit;
1871  $context->getOutput()->wrapWikiMsg( "<div class='error'>\n$1\n</div>\n",
1872  [
1873  'delete-warning-toobig',
1874  $context->getLanguage()->formatNum( $wgDeleteRevisionsLimit )
1875  ]
1876  );
1877  }
1878  }
1879 
1880  $this->confirmDelete( $reason );
1881  }
1882 
1888  public function confirmDelete( $reason ) {
1889  wfDebug( "Article::confirmDelete\n" );
1890 
1891  $title = $this->getTitle();
1892  $ctx = $this->getContext();
1893  $outputPage = $ctx->getOutput();
1894  $outputPage->setPageTitle( wfMessage( 'delete-confirm', $title->getPrefixedText() ) );
1895  $outputPage->addBacklinkSubtitle( $title );
1896  $outputPage->setRobotPolicy( 'noindex,nofollow' );
1897  $outputPage->addModules( 'mediawiki.action.delete' );
1898 
1899  $backlinkCache = $title->getBacklinkCache();
1900  if ( $backlinkCache->hasLinks( 'pagelinks' ) || $backlinkCache->hasLinks( 'templatelinks' ) ) {
1901  $outputPage->wrapWikiMsg( "<div class='mw-warning plainlinks'>\n$1\n</div>\n",
1902  'deleting-backlinks-warning' );
1903  }
1904 
1905  $subpageQueryLimit = 51;
1906  $subpages = $title->getSubpages( $subpageQueryLimit );
1907  $subpageCount = count( $subpages );
1908  if ( $subpageCount > 0 ) {
1909  $outputPage->wrapWikiMsg( "<div class='mw-warning plainlinks'>\n$1\n</div>\n",
1910  [ 'deleting-subpages-warning', Message::numParam( $subpageCount ) ] );
1911  }
1912  $outputPage->addWikiMsg( 'confirmdeletetext' );
1913 
1914  Hooks::run( 'ArticleConfirmDelete', [ $this, $outputPage, &$reason ] );
1915 
1916  $user = $this->getContext()->getUser();
1917  $checkWatch = $user->getBoolOption( 'watchdeletion' ) || $user->isWatched( $title );
1918 
1919  $outputPage->enableOOUI();
1920 
1922  $ctx->msg( 'deletereason-dropdown' )->inContentLanguage()->text(),
1923  [ 'other' => $ctx->msg( 'deletereasonotherlist' )->inContentLanguage()->text() ]
1924  );
1926 
1927  $fields[] = new OOUI\FieldLayout(
1928  new OOUI\DropdownInputWidget( [
1929  'name' => 'wpDeleteReasonList',
1930  'inputId' => 'wpDeleteReasonList',
1931  'tabIndex' => 1,
1932  'infusable' => true,
1933  'value' => '',
1934  'options' => $options
1935  ] ),
1936  [
1937  'label' => $ctx->msg( 'deletecomment' )->text(),
1938  'align' => 'top',
1939  ]
1940  );
1941 
1942  // HTML maxlength uses "UTF-16 code units", which means that characters outside BMP
1943  // (e.g. emojis) count for two each. This limit is overridden in JS to instead count
1944  // Unicode codepoints (or 255 UTF-8 bytes for old schema).
1945  $conf = $this->getContext()->getConfig();
1946  $oldCommentSchema = $conf->get( 'CommentTableSchemaMigrationStage' ) === MIGRATION_OLD;
1947  $fields[] = new OOUI\FieldLayout(
1948  new OOUI\TextInputWidget( [
1949  'name' => 'wpReason',
1950  'inputId' => 'wpReason',
1951  'tabIndex' => 2,
1952  'maxLength' => $oldCommentSchema ? 255 : CommentStore::COMMENT_CHARACTER_LIMIT,
1953  'infusable' => true,
1954  'value' => $reason,
1955  'autofocus' => true,
1956  ] ),
1957  [
1958  'label' => $ctx->msg( 'deleteotherreason' )->text(),
1959  'align' => 'top',
1960  ]
1961  );
1962 
1963  if ( $user->isLoggedIn() ) {
1964  $fields[] = new OOUI\FieldLayout(
1965  new OOUI\CheckboxInputWidget( [
1966  'name' => 'wpWatch',
1967  'inputId' => 'wpWatch',
1968  'tabIndex' => 3,
1969  'selected' => $checkWatch,
1970  ] ),
1971  [
1972  'label' => $ctx->msg( 'watchthis' )->text(),
1973  'align' => 'inline',
1974  'infusable' => true,
1975  ]
1976  );
1977  }
1978 
1979  if ( $user->isAllowed( 'suppressrevision' ) ) {
1980  $fields[] = new OOUI\FieldLayout(
1981  new OOUI\CheckboxInputWidget( [
1982  'name' => 'wpSuppress',
1983  'inputId' => 'wpSuppress',
1984  'tabIndex' => 4,
1985  ] ),
1986  [
1987  'label' => $ctx->msg( 'revdelete-suppress' )->text(),
1988  'align' => 'inline',
1989  'infusable' => true,
1990  ]
1991  );
1992  }
1993 
1994  $fields[] = new OOUI\FieldLayout(
1995  new OOUI\ButtonInputWidget( [
1996  'name' => 'wpConfirmB',
1997  'inputId' => 'wpConfirmB',
1998  'tabIndex' => 5,
1999  'value' => $ctx->msg( 'deletepage' )->text(),
2000  'label' => $ctx->msg( 'deletepage' )->text(),
2001  'flags' => [ 'primary', 'destructive' ],
2002  'type' => 'submit',
2003  ] ),
2004  [
2005  'align' => 'top',
2006  ]
2007  );
2008 
2009  $fieldset = new OOUI\FieldsetLayout( [
2010  'label' => $ctx->msg( 'delete-legend' )->text(),
2011  'id' => 'mw-delete-table',
2012  'items' => $fields,
2013  ] );
2014 
2015  $form = new OOUI\FormLayout( [
2016  'method' => 'post',
2017  'action' => $title->getLocalURL( 'action=delete' ),
2018  'id' => 'deleteconfirm',
2019  ] );
2020  $form->appendContent(
2021  $fieldset,
2022  new OOUI\HtmlSnippet(
2023  Html::hidden( 'wpEditToken', $user->getEditToken( [ 'delete', $title->getPrefixedText() ] ) )
2024  )
2025  );
2026 
2027  $outputPage->addHTML(
2028  new OOUI\PanelLayout( [
2029  'classes' => [ 'deletepage-wrapper' ],
2030  'expanded' => false,
2031  'padded' => true,
2032  'framed' => true,
2033  'content' => $form,
2034  ] )
2035  );
2036 
2037  if ( $user->isAllowed( 'editinterface' ) ) {
2039  $ctx->msg( 'deletereason-dropdown' )->inContentLanguage()->getTitle(),
2040  wfMessage( 'delete-edit-reasonlist' )->escaped(),
2041  [],
2042  [ 'action' => 'edit' ]
2043  );
2044  $outputPage->addHTML( '<p class="mw-delete-editreasons">' . $link . '</p>' );
2045  }
2046 
2047  $deleteLogPage = new LogPage( 'delete' );
2048  $outputPage->addHTML( Xml::element( 'h2', null, $deleteLogPage->getName()->text() ) );
2049  LogEventsList::showLogExtract( $outputPage, 'delete', $title );
2050  }
2051 
2060  public function doDelete( $reason, $suppress = false, $immediate = false ) {
2061  $error = '';
2062  $context = $this->getContext();
2063  $outputPage = $context->getOutput();
2064  $user = $context->getUser();
2065  $status = $this->mPage->doDeleteArticleReal( $reason, $suppress, 0, true, $error, $user,
2066  [], 'delete', $immediate );
2067 
2068  if ( $status->isOK() ) {
2069  $deleted = $this->getTitle()->getPrefixedText();
2070 
2071  $outputPage->setPageTitle( wfMessage( 'actioncomplete' ) );
2072  $outputPage->setRobotPolicy( 'noindex,nofollow' );
2073 
2074  if ( $status->isGood() ) {
2075  $loglink = '[[Special:Log/delete|' . wfMessage( 'deletionlog' )->text() . ']]';
2076  $outputPage->addWikiMsg( 'deletedtext', wfEscapeWikiText( $deleted ), $loglink );
2077  Hooks::run( 'ArticleDeleteAfterSuccess', [ $this->getTitle(), $outputPage ] );
2078  } else {
2079  $outputPage->addWikiMsg( 'delete-scheduled', wfEscapeWikiText( $deleted ) );
2080  }
2081 
2082  $outputPage->returnToMain( false );
2083  } else {
2084  $outputPage->setPageTitle(
2085  wfMessage( 'cannotdelete-title',
2086  $this->getTitle()->getPrefixedText() )
2087  );
2088 
2089  if ( $error == '' ) {
2090  $outputPage->addWikiText(
2091  "<div class=\"error mw-error-cannotdelete\">\n" . $status->getWikiText() . "\n</div>"
2092  );
2093  $deleteLogPage = new LogPage( 'delete' );
2094  $outputPage->addHTML( Xml::element( 'h2', null, $deleteLogPage->getName()->text() ) );
2095 
2097  $outputPage,
2098  'delete',
2099  $this->getTitle()
2100  );
2101  } else {
2102  $outputPage->addHTML( $error );
2103  }
2104  }
2105  }
2106 
2107  /* Caching functions */
2108 
2116  protected function tryFileCache() {
2117  static $called = false;
2118 
2119  if ( $called ) {
2120  wfDebug( "Article::tryFileCache(): called twice!?\n" );
2121  return false;
2122  }
2123 
2124  $called = true;
2125  if ( $this->isFileCacheable() ) {
2126  $cache = new HTMLFileCache( $this->getTitle(), 'view' );
2127  if ( $cache->isCacheGood( $this->mPage->getTouched() ) ) {
2128  wfDebug( "Article::tryFileCache(): about to load file\n" );
2129  $cache->loadFromFileCache( $this->getContext() );
2130  return true;
2131  } else {
2132  wfDebug( "Article::tryFileCache(): starting buffer\n" );
2133  ob_start( [ &$cache, 'saveToFileCache' ] );
2134  }
2135  } else {
2136  wfDebug( "Article::tryFileCache(): not cacheable\n" );
2137  }
2138 
2139  return false;
2140  }
2141 
2147  public function isFileCacheable( $mode = HTMLFileCache::MODE_NORMAL ) {
2148  $cacheable = false;
2149 
2150  if ( HTMLFileCache::useFileCache( $this->getContext(), $mode ) ) {
2151  $cacheable = $this->mPage->getId()
2152  && !$this->mRedirectedFrom && !$this->getTitle()->isRedirect();
2153  // Extension may have reason to disable file caching on some pages.
2154  if ( $cacheable ) {
2155  // Avoid PHP 7.1 warning of passing $this by reference
2156  $articlePage = $this;
2157  $cacheable = Hooks::run( 'IsFileCacheable', [ &$articlePage ] );
2158  }
2159  }
2160 
2161  return $cacheable;
2162  }
2163 
2177  public function getParserOutput( $oldid = null, User $user = null ) {
2178  // XXX: bypasses mParserOptions and thus setParserOptions()
2179 
2180  if ( $user === null ) {
2181  $parserOptions = $this->getParserOptions();
2182  } else {
2183  $parserOptions = $this->mPage->makeParserOptions( $user );
2184  }
2185 
2186  return $this->mPage->getParserOutput( $parserOptions, $oldid );
2187  }
2188 
2196  if ( $this->mParserOptions ) {
2197  throw new MWException( "can't change parser options after they have already been set" );
2198  }
2199 
2200  // clone, so if $options is modified later, it doesn't confuse the parser cache.
2201  $this->mParserOptions = clone $options;
2202  }
2203 
2208  public function getParserOptions() {
2209  if ( !$this->mParserOptions ) {
2210  $this->mParserOptions = $this->mPage->makeParserOptions( $this->getContext() );
2211  }
2212  // Clone to allow modifications of the return value without affecting cache
2213  return clone $this->mParserOptions;
2214  }
2215 
2222  public function setContext( $context ) {
2223  $this->mContext = $context;
2224  }
2225 
2232  public function getContext() {
2233  if ( $this->mContext instanceof IContextSource ) {
2234  return $this->mContext;
2235  } else {
2236  wfDebug( __METHOD__ . " called and \$mContext is null. " .
2237  "Return RequestContext::getMain(); for sanity\n" );
2238  return RequestContext::getMain();
2239  }
2240  }
2241 
2249  public function __get( $fname ) {
2250  if ( property_exists( $this->mPage, $fname ) ) {
2251  # wfWarn( "Access to raw $fname field " . __CLASS__ );
2252  return $this->mPage->$fname;
2253  }
2254  trigger_error( 'Inaccessible property via __get(): ' . $fname, E_USER_NOTICE );
2255  }
2256 
2264  public function __set( $fname, $fvalue ) {
2265  if ( property_exists( $this->mPage, $fname ) ) {
2266  # wfWarn( "Access to raw $fname field of " . __CLASS__ );
2267  $this->mPage->$fname = $fvalue;
2268  // Note: extensions may want to toss on new fields
2269  } elseif ( !in_array( $fname, [ 'mContext', 'mPage' ] ) ) {
2270  $this->mPage->$fname = $fvalue;
2271  } else {
2272  trigger_error( 'Inaccessible property via __set(): ' . $fname, E_USER_NOTICE );
2273  }
2274  }
2275 
2280  public function checkFlags( $flags ) {
2281  return $this->mPage->checkFlags( $flags );
2282  }
2283 
2288  public function checkTouched() {
2289  return $this->mPage->checkTouched();
2290  }
2291 
2296  public function clearPreparedEdit() {
2297  $this->mPage->clearPreparedEdit();
2298  }
2299 
2304  public function doDeleteArticleReal(
2305  $reason, $suppress = false, $u1 = null, $u2 = null, &$error = '', User $user = null,
2306  $tags = [], $immediate = false
2307  ) {
2308  return $this->mPage->doDeleteArticleReal(
2309  $reason, $suppress, $u1, $u2, $error, $user, $tags, 'delete', $immediate
2310  );
2311  }
2312 
2317  public function doDeleteUpdates(
2318  $id,
2319  Content $content = null,
2320  $revision = null,
2321  User $user = null
2322  ) {
2323  $this->mPage->doDeleteUpdates( $id, $content, $revision, $user );
2324  }
2325 
2331  public function doEditContent( Content $content, $summary, $flags = 0, $originalRevId = false,
2332  User $user = null, $serialFormat = null
2333  ) {
2334  wfDeprecated( __METHOD__, '1.29' );
2335  return $this->mPage->doEditContent( $content, $summary, $flags, $originalRevId,
2336  $user, $serialFormat
2337  );
2338  }
2339 
2344  public function doEditUpdates( Revision $revision, User $user, array $options = [] ) {
2345  return $this->mPage->doEditUpdates( $revision, $user, $options );
2346  }
2347 
2354  public function doPurge() {
2355  return $this->mPage->doPurge();
2356  }
2357 
2362  public function doViewUpdates( User $user, $oldid = 0 ) {
2363  $this->mPage->doViewUpdates( $user, $oldid );
2364  }
2365 
2370  public function exists() {
2371  return $this->mPage->exists();
2372  }
2373 
2378  public function followRedirect() {
2379  return $this->mPage->followRedirect();
2380  }
2381 
2386  public function getActionOverrides() {
2387  return $this->mPage->getActionOverrides();
2388  }
2389 
2394  public function getAutoDeleteReason( &$hasHistory ) {
2395  return $this->mPage->getAutoDeleteReason( $hasHistory );
2396  }
2397 
2402  public function getCategories() {
2403  return $this->mPage->getCategories();
2404  }
2405 
2410  public function getComment( $audience = Revision::FOR_PUBLIC, User $user = null ) {
2411  return $this->mPage->getComment( $audience, $user );
2412  }
2413 
2418  public function getContentHandler() {
2419  return $this->mPage->getContentHandler();
2420  }
2421 
2426  public function getContentModel() {
2427  return $this->mPage->getContentModel();
2428  }
2429 
2434  public function getContributors() {
2435  return $this->mPage->getContributors();
2436  }
2437 
2442  public function getCreator( $audience = Revision::FOR_PUBLIC, User $user = null ) {
2443  return $this->mPage->getCreator( $audience, $user );
2444  }
2445 
2450  public function getDeletionUpdates( Content $content = null ) {
2451  return $this->mPage->getDeletionUpdates( $content );
2452  }
2453 
2458  public function getHiddenCategories() {
2459  return $this->mPage->getHiddenCategories();
2460  }
2461 
2466  public function getId() {
2467  return $this->mPage->getId();
2468  }
2469 
2474  public function getLatest() {
2475  return $this->mPage->getLatest();
2476  }
2477 
2482  public function getLinksTimestamp() {
2483  return $this->mPage->getLinksTimestamp();
2484  }
2485 
2490  public function getMinorEdit() {
2491  return $this->mPage->getMinorEdit();
2492  }
2493 
2498  public function getOldestRevision() {
2499  return $this->mPage->getOldestRevision();
2500  }
2501 
2506  public function getRedirectTarget() {
2507  return $this->mPage->getRedirectTarget();
2508  }
2509 
2514  public function getRedirectURL( $rt ) {
2515  return $this->mPage->getRedirectURL( $rt );
2516  }
2517 
2522  public function getRevision() {
2523  return $this->mPage->getRevision();
2524  }
2525 
2530  public function getTimestamp() {
2531  return $this->mPage->getTimestamp();
2532  }
2533 
2538  public function getTouched() {
2539  return $this->mPage->getTouched();
2540  }
2541 
2546  public function getUndoContent( Revision $undo, Revision $undoafter = null ) {
2547  return $this->mPage->getUndoContent( $undo, $undoafter );
2548  }
2549 
2554  public function getUser( $audience = Revision::FOR_PUBLIC, User $user = null ) {
2555  return $this->mPage->getUser( $audience, $user );
2556  }
2557 
2562  public function getUserText( $audience = Revision::FOR_PUBLIC, User $user = null ) {
2563  return $this->mPage->getUserText( $audience, $user );
2564  }
2565 
2570  public function hasViewableContent() {
2571  return $this->mPage->hasViewableContent();
2572  }
2573 
2578  public function insertOn( $dbw, $pageId = null ) {
2579  return $this->mPage->insertOn( $dbw, $pageId );
2580  }
2581 
2586  public function insertProtectNullRevision( $revCommentMsg, array $limit,
2587  array $expiry, $cascade, $reason, $user = null
2588  ) {
2589  return $this->mPage->insertProtectNullRevision( $revCommentMsg, $limit,
2590  $expiry, $cascade, $reason, $user
2591  );
2592  }
2593 
2598  public function insertRedirect() {
2599  return $this->mPage->insertRedirect();
2600  }
2601 
2606  public function insertRedirectEntry( Title $rt, $oldLatest = null ) {
2607  return $this->mPage->insertRedirectEntry( $rt, $oldLatest );
2608  }
2609 
2614  public function isCountable( $editInfo = false ) {
2615  return $this->mPage->isCountable( $editInfo );
2616  }
2617 
2622  public function isRedirect() {
2623  return $this->mPage->isRedirect();
2624  }
2625 
2630  public function loadFromRow( $data, $from ) {
2631  return $this->mPage->loadFromRow( $data, $from );
2632  }
2633 
2638  public function loadPageData( $from = 'fromdb' ) {
2639  $this->mPage->loadPageData( $from );
2640  }
2641 
2646  public function lockAndGetLatest() {
2647  return $this->mPage->lockAndGetLatest();
2648  }
2649 
2654  public function makeParserOptions( $context ) {
2655  return $this->mPage->makeParserOptions( $context );
2656  }
2657 
2662  public function pageDataFromId( $dbr, $id, $options = [] ) {
2663  return $this->mPage->pageDataFromId( $dbr, $id, $options );
2664  }
2665 
2670  public function pageDataFromTitle( $dbr, $title, $options = [] ) {
2671  return $this->mPage->pageDataFromTitle( $dbr, $title, $options );
2672  }
2673 
2678  public function prepareContentForEdit(
2679  Content $content, $revision = null, User $user = null,
2680  $serialFormat = null, $useCache = true
2681  ) {
2682  return $this->mPage->prepareContentForEdit(
2683  $content, $revision, $user,
2684  $serialFormat, $useCache
2685  );
2686  }
2687 
2692  public function protectDescription( array $limit, array $expiry ) {
2693  return $this->mPage->protectDescription( $limit, $expiry );
2694  }
2695 
2700  public function protectDescriptionLog( array $limit, array $expiry ) {
2701  return $this->mPage->protectDescriptionLog( $limit, $expiry );
2702  }
2703 
2708  public function replaceSectionAtRev( $sectionId, Content $sectionContent,
2709  $sectionTitle = '', $baseRevId = null
2710  ) {
2711  return $this->mPage->replaceSectionAtRev( $sectionId, $sectionContent,
2712  $sectionTitle, $baseRevId
2713  );
2714  }
2715 
2720  public function replaceSectionContent(
2721  $sectionId, Content $sectionContent, $sectionTitle = '', $edittime = null
2722  ) {
2723  return $this->mPage->replaceSectionContent(
2724  $sectionId, $sectionContent, $sectionTitle, $edittime
2725  );
2726  }
2727 
2732  public function setTimestamp( $ts ) {
2733  return $this->mPage->setTimestamp( $ts );
2734  }
2735 
2740  public function shouldCheckParserCache( ParserOptions $parserOptions, $oldId ) {
2741  return $this->mPage->shouldCheckParserCache( $parserOptions, $oldId );
2742  }
2743 
2748  public function supportsSections() {
2749  return $this->mPage->supportsSections();
2750  }
2751 
2756  public function triggerOpportunisticLinksUpdate( ParserOutput $parserOutput ) {
2757  return $this->mPage->triggerOpportunisticLinksUpdate( $parserOutput );
2758  }
2759 
2764  public function updateCategoryCounts( array $added, array $deleted, $id = 0 ) {
2765  return $this->mPage->updateCategoryCounts( $added, $deleted, $id );
2766  }
2767 
2772  public function updateIfNewerOn( $dbw, $revision ) {
2773  return $this->mPage->updateIfNewerOn( $dbw, $revision );
2774  }
2775 
2780  public function updateRedirectOn( $dbw, $redirectTitle, $lastRevIsRedirect = null ) {
2781  return $this->mPage->updateRedirectOn( $dbw, $redirectTitle, $lastRevIsRedirect );
2782  }
2783 
2788  public function updateRevisionOn( $dbw, $revision, $lastRevision = null,
2789  $lastRevIsRedirect = null
2790  ) {
2791  return $this->mPage->updateRevisionOn( $dbw, $revision, $lastRevision,
2792  $lastRevIsRedirect
2793  );
2794  }
2795 
2804  public function doUpdateRestrictions( array $limit, array $expiry, &$cascade,
2805  $reason, User $user
2806  ) {
2807  return $this->mPage->doUpdateRestrictions( $limit, $expiry, $cascade, $reason, $user );
2808  }
2809 
2817  public function updateRestrictions( $limit = [], $reason = '',
2818  &$cascade = 0, $expiry = []
2819  ) {
2820  return $this->mPage->doUpdateRestrictions(
2821  $limit,
2822  $expiry,
2823  $cascade,
2824  $reason,
2825  $this->getContext()->getUser()
2826  );
2827  }
2828 
2840  public function doDeleteArticle(
2841  $reason, $suppress = false, $u1 = null, $u2 = null, &$error = '', $immediate = false
2842  ) {
2843  return $this->mPage->doDeleteArticle( $reason, $suppress, $u1, $u2, $error,
2844  null, $immediate );
2845  }
2846 
2856  public function doRollback( $fromP, $summary, $token, $bot, &$resultDetails, User $user = null ) {
2857  $user = is_null( $user ) ? $this->getContext()->getUser() : $user;
2858  return $this->mPage->doRollback( $fromP, $summary, $token, $bot, $resultDetails, $user );
2859  }
2860 
2869  public function commitRollback( $fromP, $summary, $bot, &$resultDetails, User $guser = null ) {
2870  $guser = is_null( $guser ) ? $this->getContext()->getUser() : $guser;
2871  return $this->mPage->commitRollback( $fromP, $summary, $bot, $resultDetails, $guser );
2872  }
2873 
2878  public function generateReason( &$hasHistory ) {
2879  $title = $this->mPage->getTitle();
2881  return $handler->getAutoDeleteReason( $title, $hasHistory );
2882  }
2883 
2884  // ******
2885 }
ReadOnlyError
Show an error when the wiki is locked/read-only and the user tries to do something that requires writ...
Definition: ReadOnlyError.php:28
$wgSend404Code
$wgSend404Code
Some web hosts attempt to rewrite all responses with a 404 (not found) status code,...
Definition: DefaultSettings.php:3534
Revision\FOR_PUBLIC
const FOR_PUBLIC
Definition: Revision.php:55
Article\showMissingArticle
showMissingArticle()
Show the error text for a missing article.
Definition: Article.php:1350
Article\checkFlags
checkFlags( $flags)
Call to WikiPage function for backwards compatibility.
Definition: Article.php:2280
$status
Status::newGood()` to allow deletion, and then `return false` from the hook function. Ensure you consume the 'ChangeTagAfterDelete' hook to carry out custom deletion actions. $tag:name of the tag $user:user initiating the action & $status:Status object. See above. 'ChangeTagsListActive':Allows you to nominate which of the tags your extension uses are in active use. & $tags:list of all active tags. Append to this array. 'ChangeTagsAfterUpdateTags':Called after tags have been updated with the ChangeTags::updateTags function. Params:$addedTags:tags effectively added in the update $removedTags:tags effectively removed in the update $prevTags:tags that were present prior to the update $rc_id:recentchanges table id $rev_id:revision table id $log_id:logging table id $params:tag params $rc:RecentChange being tagged when the tagging accompanies the action, or null $user:User who performed the tagging when the tagging is subsequent to the action, or null 'ChangeTagsAllowedAdd':Called when checking if a user can add tags to a change. & $allowedTags:List of all the tags the user is allowed to add. Any tags the user wants to add( $addTags) that are not in this array will cause it to fail. You may add or remove tags to this array as required. $addTags:List of tags user intends to add. $user:User who is adding the tags. 'ChangeUserGroups':Called before user groups are changed. $performer:The User who will perform the change $user:The User whose groups will be changed & $add:The groups that will be added & $remove:The groups that will be removed 'Collation::factory':Called if $wgCategoryCollation is an unknown collation. $collationName:Name of the collation in question & $collationObject:Null. Replace with a subclass of the Collation class that implements the collation given in $collationName. 'ConfirmEmailComplete':Called after a user 's email has been confirmed successfully. $user:user(object) whose email is being confirmed 'ContentAlterParserOutput':Modify parser output for a given content object. Called by Content::getParserOutput after parsing has finished. Can be used for changes that depend on the result of the parsing but have to be done before LinksUpdate is called(such as adding tracking categories based on the rendered HTML). $content:The Content to render $title:Title of the page, as context $parserOutput:ParserOutput to manipulate 'ContentGetParserOutput':Customize parser output for a given content object, called by AbstractContent::getParserOutput. May be used to override the normal model-specific rendering of page content. $content:The Content to render $title:Title of the page, as context $revId:The revision ID, as context $options:ParserOptions for rendering. To avoid confusing the parser cache, the output can only depend on parameters provided to this hook function, not on global state. $generateHtml:boolean, indicating whether full HTML should be generated. If false, generation of HTML may be skipped, but other information should still be present in the ParserOutput object. & $output:ParserOutput, to manipulate or replace 'ContentHandlerDefaultModelFor':Called when the default content model is determined for a given title. May be used to assign a different model for that title. $title:the Title in question & $model:the model name. Use with CONTENT_MODEL_XXX constants. 'ContentHandlerForModelID':Called when a ContentHandler is requested for a given content model name, but no entry for that model exists in $wgContentHandlers. Note:if your extension implements additional models via this hook, please use GetContentModels hook to make them known to core. $modeName:the requested content model name & $handler:set this to a ContentHandler object, if desired. 'ContentModelCanBeUsedOn':Called to determine whether that content model can be used on a given page. This is especially useful to prevent some content models to be used in some special location. $contentModel:ID of the content model in question $title:the Title in question. & $ok:Output parameter, whether it is OK to use $contentModel on $title. Handler functions that modify $ok should generally return false to prevent further hooks from further modifying $ok. 'ContribsPager::getQueryInfo':Before the contributions query is about to run & $pager:Pager object for contributions & $queryInfo:The query for the contribs Pager 'ContribsPager::reallyDoQuery':Called before really executing the query for My Contributions & $data:an array of results of all contribs queries $pager:The ContribsPager object hooked into $offset:Index offset, inclusive $limit:Exact query limit $descending:Query direction, false for ascending, true for descending 'ContributionsLineEnding':Called before a contributions HTML line is finished $page:SpecialPage object for contributions & $ret:the HTML line $row:the DB row for this line & $classes:the classes to add to the surrounding< li > & $attribs:associative array of other HTML attributes for the< li > element. Currently only data attributes reserved to MediaWiki are allowed(see Sanitizer::isReservedDataAttribute). 'ContributionsToolLinks':Change tool links above Special:Contributions $id:User identifier $title:User page title & $tools:Array of tool links $specialPage:SpecialPage instance for context and services. Can be either SpecialContributions or DeletedContributionsPage. Extensions should type hint against a generic SpecialPage though. 'ConvertContent':Called by AbstractContent::convert when a conversion to another content model is requested. Handler functions that modify $result should generally return false to disable further attempts at conversion. $content:The Content object to be converted. $toModel:The ID of the content model to convert to. $lossy:boolean indicating whether lossy conversion is allowed. & $result:Output parameter, in case the handler function wants to provide a converted Content object. Note that $result->getContentModel() must return $toModel. 'ContentSecurityPolicyDefaultSource':Modify the allowed CSP load sources. This affects all directives except for the script directive. If you want to add a script source, see ContentSecurityPolicyScriptSource hook. & $defaultSrc:Array of Content-Security-Policy allowed sources $policyConfig:Current configuration for the Content-Security-Policy header $mode:ContentSecurityPolicy::REPORT_ONLY_MODE or ContentSecurityPolicy::FULL_MODE depending on type of header 'ContentSecurityPolicyDirectives':Modify the content security policy directives. Use this only if ContentSecurityPolicyDefaultSource and ContentSecurityPolicyScriptSource do not meet your needs. & $directives:Array of CSP directives $policyConfig:Current configuration for the CSP header $mode:ContentSecurityPolicy::REPORT_ONLY_MODE or ContentSecurityPolicy::FULL_MODE depending on type of header 'ContentSecurityPolicyScriptSource':Modify the allowed CSP script sources. Note that you also have to use ContentSecurityPolicyDefaultSource if you want non-script sources to be loaded from whatever you add. & $scriptSrc:Array of CSP directives $policyConfig:Current configuration for the CSP header $mode:ContentSecurityPolicy::REPORT_ONLY_MODE or ContentSecurityPolicy::FULL_MODE depending on type of header 'CustomEditor':When invoking the page editor Return true to allow the normal editor to be used, or false if implementing a custom editor, e.g. for a special namespace, etc. $article:Article being edited $user:User performing the edit 'DatabaseOraclePostInit':Called after initialising an Oracle database $db:the DatabaseOracle object 'DeletedContribsPager::reallyDoQuery':Called before really executing the query for Special:DeletedContributions Similar to ContribsPager::reallyDoQuery & $data:an array of results of all contribs queries $pager:The DeletedContribsPager object hooked into $offset:Index offset, inclusive $limit:Exact query limit $descending:Query direction, false for ascending, true for descending 'DeletedContributionsLineEnding':Called before a DeletedContributions HTML line is finished. Similar to ContributionsLineEnding $page:SpecialPage object for DeletedContributions & $ret:the HTML line $row:the DB row for this line & $classes:the classes to add to the surrounding< li > & $attribs:associative array of other HTML attributes for the< li > element. Currently only data attributes reserved to MediaWiki are allowed(see Sanitizer::isReservedDataAttribute). 'DeleteUnknownPreferences':Called by the cleanupPreferences.php maintenance script to build a WHERE clause with which to delete preferences that are not known about. This hook is used by extensions that have dynamically-named preferences that should not be deleted in the usual cleanup process. For example, the Gadgets extension creates preferences prefixed with 'gadget-', and so anything with that prefix is excluded from the deletion. &where:An array that will be passed as the $cond parameter to IDatabase::select() to determine what will be deleted from the user_properties table. $db:The IDatabase object, useful for accessing $db->buildLike() etc. 'DifferenceEngineAfterLoadNewText':called in DifferenceEngine::loadNewText() after the new revision 's content has been loaded into the class member variable $differenceEngine->mNewContent but before returning true from this function. $differenceEngine:DifferenceEngine object 'DifferenceEngineLoadTextAfterNewContentIsLoaded':called in DifferenceEngine::loadText() after the new revision 's content has been loaded into the class member variable $differenceEngine->mNewContent but before checking if the variable 's value is null. This hook can be used to inject content into said class member variable. $differenceEngine:DifferenceEngine object 'DifferenceEngineMarkPatrolledLink':Allows extensions to change the "mark as patrolled" link which is shown both on the diff header as well as on the bottom of a page, usually wrapped in a span element which has class="patrollink". $differenceEngine:DifferenceEngine object & $markAsPatrolledLink:The "mark as patrolled" link HTML(string) $rcid:Recent change ID(rc_id) for this change(int) 'DifferenceEngineMarkPatrolledRCID':Allows extensions to possibly change the rcid parameter. For example the rcid might be set to zero due to the user being the same as the performer of the change but an extension might still want to show it under certain conditions. & $rcid:rc_id(int) of the change or 0 $differenceEngine:DifferenceEngine object $change:RecentChange object $user:User object representing the current user 'DifferenceEngineNewHeader':Allows extensions to change the $newHeader variable, which contains information about the new revision, such as the revision 's author, whether the revision was marked as a minor edit or not, etc. $differenceEngine:DifferenceEngine object & $newHeader:The string containing the various #mw-diff-otitle[1-5] divs, which include things like revision author info, revision comment, RevisionDelete link and more $formattedRevisionTools:Array containing revision tools, some of which may have been injected with the DiffRevisionTools hook $nextlink:String containing the link to the next revision(if any) $status
Definition: hooks.txt:1305
ParserOptions
Set options of the Parser.
Definition: ParserOptions.php:42
Article\$mContentObject
Content null $mContentObject
Content of the main slot of $this->mRevision.
Definition: Article.php:62
HTMLFileCache\useFileCache
static useFileCache(IContextSource $context, $mode=self::MODE_NORMAL)
Check if pages can be cached for this request/user.
Definition: HTMLFileCache.php:93
Article\$mContext
IContextSource null $mContext
The context this Article is executed in.
Definition: Article.php:43
Html\errorBox
static errorBox( $html, $heading='')
Return an error box.
Definition: Html.php:734
$user
please add to it if you re going to add events to the MediaWiki code where normally authentication against an external auth plugin would be creating a account $user
Definition: hooks.txt:244
Page
Interface for type hinting (accepts WikiPage, Article, ImagePage, CategoryPage)
Definition: Page.php:24
Revision\DELETED_RESTRICTED
const DELETED_RESTRICTED
Definition: Revision.php:50
$article
return true to allow those checks to and false if checking is done remove or add to the links of a group of changes in EnhancedChangesList Hook subscribers can return false to omit this line from recentchanges use this to change the tables headers change it to an object instance and return false override the list derivative used the name of the old file & $article
Definition: hooks.txt:1515
Article\isRedirect
isRedirect()
Call to WikiPage function for backwards compatibility.
Definition: Article.php:2622
Article\getCategories
getCategories()
Call to WikiPage function for backwards compatibility.
Definition: Article.php:2402
Article\doDeleteArticleReal
doDeleteArticleReal( $reason, $suppress=false, $u1=null, $u2=null, &$error='', User $user=null, $tags=[], $immediate=false)
Call to WikiPage function for backwards compatibility.
Definition: Article.php:2304
Revision\RevisionRecord
Page revision base class.
Definition: RevisionRecord.php:45
ParserOutput
Definition: ParserOutput.php:25
Article\formatRobotPolicy
static formatRobotPolicy( $policy)
Converts a String robot policy into an associative array, to allow merging of several policies using ...
Definition: Article.php:1029
Article\getRedirectTarget
getRedirectTarget()
Call to WikiPage function for backwards compatibility.
Definition: Article.php:2506
Article\view
view()
This is the default action of the index.php entry point: just view the page of the given title.
Definition: Article.php:587
Revision\newFromId
static newFromId( $id, $flags=0)
Load a page revision from a given revision ID number.
Definition: Revision.php:114
$context
do that in ParserLimitReportFormat instead use this to modify the parameters of the image all existing parser cache entries will be invalid To avoid you ll need to handle that somehow(e.g. with the RejectParserCacheValue hook) because MediaWiki won 't do it for you. & $defaults also a ContextSource after deleting those rows but within the same transaction you ll probably need to make sure the header is varied on and they can depend only on the ResourceLoaderContext $context
Definition: hooks.txt:2675
Xml\listDropDownOptionsOoui
static listDropDownOptionsOoui( $options)
Convert options for a drop-down box into a format accepted by OOUI\DropdownInputWidget etc.
Definition: Xml.php:583
Article\getContentModel
getContentModel()
Call to WikiPage function for backwards compatibility.
Definition: Article.php:2426
Article\getUserText
getUserText( $audience=Revision::FOR_PUBLIC, User $user=null)
Call to WikiPage function for backwards compatibility.
Definition: Article.php:2562
Article\getLinksTimestamp
getLinksTimestamp()
Call to WikiPage function for backwards compatibility.
Definition: Article.php:2482
Article\$disableSectionEditForRender
bool $disableSectionEditForRender
Whether render() was called.
Definition: Article.php:123
Article\getOldIDFromRequest
getOldIDFromRequest()
Sets $this->mRedirectUrl to a correct URL if the query parameters are incorrect.
Definition: Article.php:339
Article\showPatrolFooter
showPatrolFooter()
If patrol is possible, output a patrol UI box.
Definition: Article.php:1172
$lang
if(!isset( $args[0])) $lang
Definition: testCompression.php:33
RecentChange\newFromConds
static newFromConds( $conds, $fname=__METHOD__, $dbType=DB_REPLICA)
Find the first recent change matching some specific conditions.
Definition: RecentChange.php:204
Article\tryFileCache
tryFileCache()
checkLastModified returns true if it has taken care of all output to the client that is necessary for...
Definition: Article.php:2116
Article\getContentHandler
getContentHandler()
Call to WikiPage function for backwards compatibility.
Definition: Article.php:2418
Article\makeFetchErrorContent
makeFetchErrorContent()
Returns a Content object representing any error in $this->fetchContent, or null if there is no such e...
Definition: Article.php:505
Article\clearPreparedEdit
clearPreparedEdit()
Call to WikiPage function for backwards compatibility.
Definition: Article.php:2296
HTMLFileCache
Page view caching in the file system.
Definition: HTMLFileCache.php:33
captcha-old.count
count
Definition: captcha-old.py:249
Article\lockAndGetLatest
lockAndGetLatest()
Call to WikiPage function for backwards compatibility.
Definition: Article.php:2646
Article\supportsSections
supportsSections()
Call to WikiPage function for backwards compatibility.
Definition: Article.php:2748
Article\getOldestRevision
getOldestRevision()
Call to WikiPage function for backwards compatibility.
Definition: Article.php:2498
Article\getDeletionUpdates
getDeletionUpdates(Content $content=null)
Call to WikiPage function for backwards compatibility.
Definition: Article.php:2450
Article\checkTouched
checkTouched()
Call to WikiPage function for backwards compatibility.
Definition: Article.php:2288
Article\getRevision
getRevision()
Call to WikiPage function for backwards compatibility.
Definition: Article.php:2522
RC_LOG
const RC_LOG
Definition: Defines.php:144
CategoryPage
Special handling for category description pages, showing pages, subcategories and file that belong to...
Definition: CategoryPage.php:28
WikiPage
Class representing a MediaWiki article and history.
Definition: WikiPage.php:44
StatusValue\newFatal
static newFatal( $message)
Factory function for fatal errors.
Definition: StatusValue.php:68
PoolWorkArticleView
Definition: PoolWorkArticleView.php:28
NS_FILE
const NS_FILE
Definition: Defines.php:70
Article\getCreator
getCreator( $audience=Revision::FOR_PUBLIC, User $user=null)
Call to WikiPage function for backwards compatibility.
Definition: Article.php:2442
Block\newFromTarget
static newFromTarget( $specificTarget, $vagueTarget=null, $fromMaster=false)
Given a target and the target's type, get an existing Block object if possible.
Definition: Block.php:1174
wfReadOnly
wfReadOnly()
Check whether the wiki is in read-only mode.
Definition: GlobalFunctions.php:1237
Article\$mRevision
Revision null $mRevision
Revision to be shown.
Definition: Article.php:109
User\newFromName
static newFromName( $name, $validate='valid')
Static factory method for creation from username.
Definition: User.php:592
Linker\linkKnown
static linkKnown( $target, $html=null, $customAttribs=[], $query=[], $options=[ 'known'])
Identical to link(), except $options defaults to 'known'.
Definition: Linker.php:141
Article\showDiffPage
showDiffPage()
Show a diff page according to current request variables.
Definition: Article.php:899
ContentHandler\getForTitle
static getForTitle(Title $title)
Returns the appropriate ContentHandler singleton for the given title.
Definition: ContentHandler.php:244
$wgArticleRobotPolicies
$wgArticleRobotPolicies
Robot policies per article.
Definition: DefaultSettings.php:8068
ImagePage
Class for viewing MediaWiki file description pages.
Definition: ImagePage.php:30
PermissionsError
Show an error when a user tries to do something they do not have the necessary permissions for.
Definition: PermissionsError.php:28
Article\confirmDelete
confirmDelete( $reason)
Output deletion confirmation dialog.
Definition: Article.php:1888
Article\updateCategoryCounts
updateCategoryCounts(array $added, array $deleted, $id=0)
Call to WikiPage function for backwards compatibility.
Definition: Article.php:2764
Article\doDeleteArticle
doDeleteArticle( $reason, $suppress=false, $u1=null, $u2=null, &$error='', $immediate=false)
Definition: Article.php:2840
Article\adjustDisplayTitle
adjustDisplayTitle(ParserOutput $pOutput)
Adjust title for pages with displaytitle, -{T|}- or language conversion.
Definition: Article.php:884
Article\showNamespaceHeader
showNamespaceHeader()
Show a header specific to the namespace currently being viewed, like [[MediaWiki:Talkpagetext]].
Definition: Article.php:1135
Article\shouldCheckParserCache
shouldCheckParserCache(ParserOptions $parserOptions, $oldId)
Call to WikiPage function for backwards compatibility.
Definition: Article.php:2740
$wgUseRCPatrol
$wgUseRCPatrol
Use RC Patrolling to check for vandalism (from recent changes and watchlists) New pages and new files...
Definition: DefaultSettings.php:6933
Xml\openElement
static openElement( $element, $attribs=null)
This opens an XML element.
Definition: Xml.php:110
$wgUseNPPatrol
$wgUseNPPatrol
Use new page patrolling to check new pages on Special:Newpages.
Definition: DefaultSettings.php:6949
ProtectionForm
Handles the page protection UI and backend.
Definition: ProtectionForm.php:30
php
injection txt This is an overview of how MediaWiki makes use of dependency injection The design described here grew from the discussion of RFC T384 The term dependency this means that anything an object needs to operate should be injected from the the object itself should only know narrow no concrete implementation of the logic it relies on The requirement to inject everything typically results in an architecture that based on two main types of and essentially stateless service objects that use other service objects to operate on the value objects As of the beginning MediaWiki is only starting to use the DI approach Much of the code still relies on global state or direct resulting in a highly cyclical dependency which acts as the top level factory for services in MediaWiki which can be used to gain access to default instances of various services MediaWikiServices however also allows new services to be defined and default services to be redefined Services are defined or redefined by providing a callback the instantiator that will return a new instance of the service When it will create an instance of MediaWikiServices and populate it with the services defined in the files listed by thereby bootstrapping the DI framework Per $wgServiceWiringFiles lists includes ServiceWiring php
Definition: injection.txt:35
Article\doDelete
doDelete( $reason, $suppress=false, $immediate=false)
Perform a deletion and output success or failure messages.
Definition: Article.php:2060
Article\protectDescriptionLog
protectDescriptionLog(array $limit, array $expiry)
Call to WikiPage function for backwards compatibility.
Definition: Article.php:2700
Article\getRevisionRedirectTarget
getRevisionRedirectTarget(RevisionRecord $revision)
Definition: Article.php:872
Article\$mRedirectedFrom
Title null $mRedirectedFrom
Title from which we were redirected here, if any.
Definition: Article.php:80
Article\doEditContent
doEditContent(Content $content, $summary, $flags=0, $originalRevId=false, User $user=null, $serialFormat=null)
Call to WikiPage function for backwards compatibility.
Definition: Article.php:2331
$dbr
$dbr
Definition: testCompression.php:50
Status
Generic operation result class Has warning/error list, boolean status and arbitrary value.
Definition: Status.php:40
Article\getSubstituteContent
getSubstituteContent()
Returns Content object to use when the page does not exist.
Definition: Article.php:286
Revision\FOR_THIS_USER
const FOR_THIS_USER
Definition: Revision.php:56
Revision
Definition: Revision.php:41
Article\unprotect
unprotect()
action=unprotect handler (alias)
Definition: Article.php:1753
Article\insertRedirect
insertRedirect()
Call to WikiPage function for backwards compatibility.
Definition: Article.php:2598
$query
null for the wiki Added should default to null in handler for backwards compatibility add a value to it if you want to add a cookie that have to vary cache options can modify $query
Definition: hooks.txt:1627
Article\getRedirectedFrom
getRedirectedFrom()
Get the page this view was redirected from.
Definition: Article.php:203
Article\fetchContentObject
fetchContentObject()
Get text content object Does NOT follow redirects.
Definition: Article.php:400
Article\clear
clear()
Clear the object.
Definition: Article.php:238
Article\updateRedirectOn
updateRedirectOn( $dbw, $redirectTitle, $lastRevIsRedirect=null)
Call to WikiPage function for backwards compatibility.
Definition: Article.php:2780
Article\newFromWikiPage
static newFromWikiPage(WikiPage $page, IContextSource $context)
Create an Article object of the appropriate class for the given page.
Definition: Article.php:192
Article\getTouched
getTouched()
Call to WikiPage function for backwards compatibility.
Definition: Article.php:2538
$html
null means default in associative array with keys and values unescaped Should be merged with default with a value of false meaning to suppress the attribute in associative array with keys and values unescaped noclasses just before the function returns a value If you return an< a > element with HTML attributes $attribs and contents $html will be returned If you return $ret will be returned and may include noclasses & $html
Definition: hooks.txt:2036
MWException
MediaWiki exception.
Definition: MWException.php:26
$title
namespace and then decline to actually register it file or subcat img or subcat $title
Definition: hooks.txt:964
Article\getTitle
getTitle()
Get the title object of the article.
Definition: Article.php:221
Article\updateRevisionOn
updateRevisionOn( $dbw, $revision, $lastRevision=null, $lastRevIsRedirect=null)
Call to WikiPage function for backwards compatibility.
Definition: Article.php:2788
Article\render
render()
Handle action=render.
Definition: Article.php:1735
wfDeprecated
wfDeprecated( $function, $version=false, $component=false, $callerOffset=2)
Throws a warning that $function is deprecated.
Definition: GlobalFunctions.php:1118
Article\insertProtectNullRevision
insertProtectNullRevision( $revCommentMsg, array $limit, array $expiry, $cascade, $reason, $user=null)
Call to WikiPage function for backwards compatibility.
Definition: Article.php:2586
Article\$mParserOutput
ParserOutput null false $mParserOutput
The ParserOutput generated for viewing the page, initialized by view().
Definition: Article.php:116
Article\addHelpLink
addHelpLink( $to, $overrideBaseUrl=false)
Adds help link with an icon via page indicators.
Definition: Article.php:1718
Article\exists
exists()
Call to WikiPage function for backwards compatibility.
Definition: Article.php:2370
Article\setRedirectedFrom
setRedirectedFrom(Title $from)
Tell the page view functions that this view was redirected from another page on the wiki.
Definition: Article.php:212
$wgUseFileCache
$wgUseFileCache
This will cache static pages for non-logged-in users to reduce database traffic on public sites.
Definition: DefaultSettings.php:2634
wfGetDB
wfGetDB( $db, $groups=[], $wiki=false)
Get a Database object.
Definition: GlobalFunctions.php:2693
Linker\revUserTools
static revUserTools( $rev, $isPublic=false)
Generate a user tool link cluster if the current user is allowed to view it.
Definition: Linker.php:1053
Article\applyContentOverride
applyContentOverride(Content $override)
Applies a content override by constructing a fake Revision object and assigning it to mRevision.
Definition: Article.php:525
Article\__construct
__construct(Title $title, $oldId=null)
Constructor and clear the article.
Definition: Article.php:130
in
null for the wiki Added in
Definition: hooks.txt:1627
Article\showDeletedRevisionHeader
showDeletedRevisionHeader()
If the revision requested for view is deleted, check permissions.
Definition: Article.php:1478
IExpiringStore\TTL_DAY
const TTL_DAY
Definition: IExpiringStore.php:36
Article\isFileCacheable
isFileCacheable( $mode=HTMLFileCache::MODE_NORMAL)
Check if the page can be cached.
Definition: Article.php:2147
Article\doRollback
doRollback( $fromP, $summary, $token, $bot, &$resultDetails, User $user=null)
Definition: Article.php:2856
not
if not
Definition: COPYING.txt:307
WikiPage\getTitle
getTitle()
Get the title object of the article.
Definition: WikiPage.php:276
LogPage
Class to simplify the use of log pages.
Definition: LogPage.php:33
Article\setOldSubtitle
setOldSubtitle( $oldid=0)
Generate the navigation links when browsing through an article revisions It shows the information as:...
Definition: Article.php:1521
Xml\element
static element( $element, $attribs=null, $contents='', $allowShortTag=true)
Format an XML element with given attributes and, optionally, text content.
Definition: Xml.php:41
Article\getPage
getPage()
Get the WikiPage object of this instance.
Definition: Article.php:231
Article\getContext
getContext()
Gets the context this Article is executed in.
Definition: Article.php:2232
User\isIP
static isIP( $name)
Does the string match an anonymous IP address?
Definition: User.php:971
use
as see the revision history and available at free of to any person obtaining a copy of this software and associated documentation to deal in the Software without including without limitation the rights to use
Definition: MIT-LICENSE.txt:10
Article\$mParserOptions
ParserOptions null $mParserOptions
ParserOptions object for $wgUser articles.
Definition: Article.php:52
WatchAction\doWatchOrUnwatch
static doWatchOrUnwatch( $watch, Title $title, User $user)
Watch or unwatch a page.
Definition: WatchAction.php:89
Article\getComment
getComment( $audience=Revision::FOR_PUBLIC, User $user=null)
Call to WikiPage function for backwards compatibility.
Definition: Article.php:2410
Article\pageDataFromId
pageDataFromId( $dbr, $id, $options=[])
Call to WikiPage function for backwards compatibility.
Definition: Article.php:2662
Article\getRobotPolicy
getRobotPolicy( $action, ParserOutput $pOutput=null)
Get the robot policy to be used for the current view.
Definition: Article.php:949
Article\insertOn
insertOn( $dbw, $pageId=null)
Call to WikiPage function for backwards compatibility.
Definition: Article.php:2578
Linker\makeExternalLink
static makeExternalLink( $url, $text, $escape=true, $linktype='', $attribs=[], $title=null)
Make an external link.
Definition: Linker.php:826
Title\makeTitle
static makeTitle( $ns, $title, $fragment='', $interwiki='')
Create a new Title from a namespace index and a DB key.
Definition: Title.php:545
Article\getRedirectURL
getRedirectURL( $rt)
Call to WikiPage function for backwards compatibility.
Definition: Article.php:2514
LogEventsList\showLogExtract
static showLogExtract(&$out, $types=[], $page='', $user='', $param=[])
Show log extract.
Definition: LogEventsList.php:606
DB_REPLICA
const DB_REPLICA
Definition: defines.php:25
Article\newFromID
static newFromID( $id)
Constructor from a page id.
Definition: Article.php:148
Article\newPage
newPage(Title $title)
Definition: Article.php:139
NS_CATEGORY
const NS_CATEGORY
Definition: Defines.php:78
Article\getUndoContent
getUndoContent(Revision $undo, Revision $undoafter=null)
Call to WikiPage function for backwards compatibility.
Definition: Article.php:2546
Article\prepareContentForEdit
prepareContentForEdit(Content $content, $revision=null, User $user=null, $serialFormat=null, $useCache=true)
Call to WikiPage function for backwards compatibility.
Definition: Article.php:2678
$wgDeleteRevisionsLimit
$wgDeleteRevisionsLimit
Optional to restrict deletion of pages with higher revision counts to users with the 'bigdelete' perm...
Definition: DefaultSettings.php:5540
array
The wiki should then use memcached to cache various data To use multiple just add more items to the array To increase the weight of a make its entry a array("192.168.0.1:11211", 2))
Article\$mRevIdFetched
int $mRevIdFetched
Revision ID of revision that was loaded.
Definition: Article.php:90
$wgUseFilePatrol
$wgUseFilePatrol
Use file patrolling to check new files on Special:Newfiles.
Definition: DefaultSettings.php:6960
Article\getLatest
getLatest()
Call to WikiPage function for backwards compatibility.
Definition: Article.php:2474
wfDebug
wfDebug( $text, $dest='all', array $context=[])
Sends a line to the debug log if enabled or, optionally, to a comment in output.
Definition: GlobalFunctions.php:988
Article\isCurrent
isCurrent()
Returns true if the currently-referenced revision is the current edit to this page (and it exists).
Definition: Article.php:541
list
deferred txt A few of the database updates required by various functions here can be deferred until after the result page is displayed to the user For updating the view updating the linked to tables after a etc PHP does not yet have any way to tell the server to actually return and disconnect while still running these but it might have such a feature in the future We handle these by creating a deferred update object and putting those objects on a global list
Definition: deferred.txt:11
ContentHandler\makeContent
static makeContent( $text, Title $title=null, $modelId=null, $format=null)
Convenience function for creating a Content object from a given textual representation.
Definition: ContentHandler.php:133
Article\getAutoDeleteReason
getAutoDeleteReason(&$hasHistory)
Call to WikiPage function for backwards compatibility.
Definition: Article.php:2394
Article\$mContentLoaded
bool $mContentLoaded
Is the target revision loaded? Set by fetchRevisionRecord().
Definition: Article.php:70
MIGRATION_OLD
const MIGRATION_OLD
Definition: Defines.php:315
Article\setParserOptions
setParserOptions(ParserOptions $options)
Override the ParserOptions used to render the primary article wikitext.
Definition: Article.php:2195
Article\isCountable
isCountable( $editInfo=false)
Call to WikiPage function for backwards compatibility.
Definition: Article.php:2614
$fname
if(defined( 'MW_SETUP_CALLBACK')) $fname
Customization point after all loading (constants, functions, classes, DefaultSettings,...
Definition: Setup.php:121
$request
do that in ParserLimitReportFormat instead use this to modify the parameters of the image all existing parser cache entries will be invalid To avoid you ll need to handle that somehow(e.g. with the RejectParserCacheValue hook) because MediaWiki won 't do it for you. & $defaults also a ContextSource after deleting those rows but within the same transaction you ll probably need to make sure the header is varied on $request
Definition: hooks.txt:2675
Html\hidden
static hidden( $name, $value, array $attribs=[])
Convenience function to produce an input element with type=hidden.
Definition: Html.php:795
ParserOutput\getTitleText
getTitleText()
Definition: ParserOutput.php:471
Article\doPurge
doPurge()
Call to WikiPage function for backwards compatibility.
Definition: Article.php:2354
Linker\revComment
static revComment(Revision $rev, $local=false, $isPublic=false)
Wrap and format the given revision's comment block, if the current user is allowed to view it.
Definition: Linker.php:1466
NS_USER_TALK
const NS_USER_TALK
Definition: Defines.php:67
$e
div flags Integer display flags(NO_ACTION_LINK, NO_EXTRA_USER_LINKS) 'LogException' returning false will NOT prevent logging $e
Definition: hooks.txt:2213
Article\hasViewableContent
hasViewableContent()
Call to WikiPage function for backwards compatibility.
Definition: Article.php:2570
Article\$mOldId
int null $mOldId
The oldid of the article that was requested to be shown, 0 for the current revision.
Definition: Article.php:77
NS_MEDIA
const NS_MEDIA
Definition: Defines.php:52
Article\getContributors
getContributors()
Call to WikiPage function for backwards compatibility.
Definition: Article.php:2434
StatusValue\newGood
static newGood( $value=null)
Factory function for good results.
Definition: StatusValue.php:81
Revision\MutableRevisionRecord
Mutable RevisionRecord implementation, for building new revision entries programmatically.
Definition: MutableRevisionRecord.php:41
HTMLFileCache\MODE_NORMAL
const MODE_NORMAL
Definition: HTMLFileCache.php:34
Article\loadFromRow
loadFromRow( $data, $from)
Call to WikiPage function for backwards compatibility.
Definition: Article.php:2630
Article\getEmptyPageParserOutput
getEmptyPageParserOutput(ParserOptions $options)
Returns ParserOutput to use when a page does not exist.
Definition: Article.php:313
Linker\getRevDeleteLink
static getRevDeleteLink(User $user, Revision $rev, Title $title)
Get a revision-deletion link, or disabled link, or nothing, depending on user permissions & the setti...
Definition: Linker.php:2051
Article\protect
protect()
action=protect handler
Definition: Article.php:1745
Article\getTimestamp
getTimestamp()
Call to WikiPage function for backwards compatibility.
Definition: Article.php:2530
Linker\link
static link( $target, $html=null, $customAttribs=[], $query=[], $options=[])
This function returns an HTML link to the given target.
Definition: Linker.php:84
ParserOptions\newCanonical
static newCanonical( $context=null, $userLang=null)
Creates a "canonical" ParserOptions object.
Definition: ParserOptions.php:1061
wfEscapeWikiText
wfEscapeWikiText( $text)
Escapes the given text so that it may be output using addWikiText() without any linking,...
Definition: GlobalFunctions.php:1617
Article\getMinorEdit
getMinorEdit()
Call to WikiPage function for backwards compatibility.
Definition: Article.php:2490
Article\commitRollback
commitRollback( $fromP, $summary, $bot, &$resultDetails, User $guser=null)
Definition: Article.php:2869
$wgNamespaceRobotPolicies
$wgNamespaceRobotPolicies
Robot policies per namespaces.
Definition: DefaultSettings.php:8040
Article\getParserOutput
getParserOutput( $oldid=null, User $user=null)
#-
Definition: Article.php:2177
Article\getUser
getUser( $audience=Revision::FOR_PUBLIC, User $user=null)
Call to WikiPage function for backwards compatibility.
Definition: Article.php:2554
Article\getContentObject
getContentObject()
Returns a Content object representing the pages effective display content, not necessarily the revisi...
Definition: Article.php:270
Article\followRedirect
followRedirect()
Call to WikiPage function for backwards compatibility.
Definition: Article.php:2378
Block\TYPE_AUTO
const TYPE_AUTO
Definition: Block.php:86
Article\getHiddenCategories
getHiddenCategories()
Call to WikiPage function for backwards compatibility.
Definition: Article.php:2458
$handler
this hook is for auditing only or null if authentication failed before getting that far or null if we can t even determine that probably a stub it is not rendered in wiki pages or galleries in category pages allow injecting custom HTML after the section Any uses of the hook need to handle escaping see BaseTemplate::getToolbox and BaseTemplate::makeListItem for details on the format of individual items inside of this array or by returning and letting standard HTTP rendering take place modifiable or by returning false and taking over the output modifiable modifiable after all normalizations have been except for the $wgMaxImageArea check set to true or false to override the $wgMaxImageArea check result gives extension the possibility to transform it themselves $handler
Definition: hooks.txt:813
RequestContext\getMain
static getMain()
Get the RequestContext object associated with the main request.
Definition: RequestContext.php:432
IP\isValid
static isValid( $ip)
Validate an IP address.
Definition: IP.php:111
Article\setTimestamp
setTimestamp( $ts)
Call to WikiPage function for backwards compatibility.
Definition: Article.php:2732
IContextSource
Interface for objects which can provide a MediaWiki context on request.
Definition: IContextSource.php:53
Article\$mPage
WikiPage null $mPage
The WikiPage object of this instance.
Definition: Article.php:46
Article\__get
__get( $fname)
Use PHP's magic __get handler to handle accessing of raw WikiPage fields for backwards compatibility.
Definition: Article.php:2249
Content
Base interface for content objects.
Definition: Content.php:34
CommentStore\COMMENT_CHARACTER_LIMIT
const COMMENT_CHARACTER_LIMIT
Maximum length of a comment in UTF-8 characters.
Definition: CommentStore.php:37
Article\replaceSectionAtRev
replaceSectionAtRev( $sectionId, Content $sectionContent, $sectionTitle='', $baseRevId=null)
Call to WikiPage function for backwards compatibility.
Definition: Article.php:2708
Hooks\isRegistered
static isRegistered( $name)
Returns true if a hook has a function registered to it.
Definition: Hooks.php:80
text
This list may contain false positives That usually means there is additional text with links below the first Each row contains links to the first and second as well as the first line of the second redirect text
Definition: All_system_messages.txt:1267
Article\fetchRevisionRecord
fetchRevisionRecord()
Fetches the revision to work on.
Definition: Article.php:417
$unhide
null for the wiki Added should default to null in handler for backwards compatibility add a value to it if you want to add a cookie that have to vary cache options can modify as strings Extensions should add to this list prev or next refreshes the diff cache $unhide
Definition: hooks.txt:1627
Title
Represents a title within MediaWiki.
Definition: Title.php:39
Skin\makeUrl
static makeUrl( $name, $urlaction='')
Definition: Skin.php:1182
$cache
$cache
Definition: mcc.php:33
$options
null means default in associative array with keys and values unescaped Should be merged with default with a value of false meaning to suppress the attribute in associative array with keys and values unescaped & $options
Definition: hooks.txt:2036
Article\replaceSectionContent
replaceSectionContent( $sectionId, Content $sectionContent, $sectionTitle='', $edittime=null)
Call to WikiPage function for backwards compatibility.
Definition: Article.php:2720
Article\getRevIdFetched
getRevIdFetched()
Use this to fetch the rev ID used on page views.
Definition: Article.php:575
MessageContent
Wrapper allowing us to handle a system message as a Content object.
Definition: MessageContent.php:36
Article\makeParserOptions
makeParserOptions( $context)
Call to WikiPage function for backwards compatibility.
Definition: Article.php:2654
Article\showRedirectedFromHeader
showRedirectedFromHeader()
If this request is a redirect view, send "redirected from" subtitle to the output.
Definition: Article.php:1058
$rev
presenting them properly to the user as errors is done by the caller return true use this to change the list i e etc $rev
Definition: hooks.txt:1808
as
This document is intended to provide useful advice for parties seeking to redistribute MediaWiki to end users It s targeted particularly at maintainers for Linux since it s been observed that distribution packages of MediaWiki often break We ve consistently had to recommend that users seeking support use official tarballs instead of their distribution s and this often solves whatever problem the user is having It would be nice if this could such as
Definition: distributors.txt:9
Block
Definition: Block.php:27
RecentChange\isInRCLifespan
static isInRCLifespan( $timestamp, $tolerance=0)
Check whether the given timestamp is new enough to have a RC row with a given tolerance as the recent...
Definition: RecentChange.php:1172
Revision\RevisionRecord\getContent
getContent( $role, $audience=self::FOR_PUBLIC, User $user=null)
Returns the Content of the given slot of this revision.
Definition: RevisionRecord.php:167
NS_USER
const NS_USER
Definition: Defines.php:66
$link
usually copyright or history_copyright This message must be in HTML not wikitext & $link
Definition: hooks.txt:3090
Article\getId
getId()
Call to WikiPage function for backwards compatibility.
Definition: Article.php:2466
Article\getActionOverrides
getActionOverrides()
Call to WikiPage function for backwards compatibility.
Definition: Article.php:2386
Article\$mRedirectUrl
string bool $mRedirectUrl
URL to redirect to or false if none.
Definition: Article.php:83
Article\doUpdateRestrictions
doUpdateRestrictions(array $limit, array $expiry, &$cascade, $reason, User $user)
Definition: Article.php:2804
$content
$content
Definition: pageupdater.txt:72
Article\updateRestrictions
updateRestrictions( $limit=[], $reason='', &$cascade=0, $expiry=[])
Definition: Article.php:2817
Article\protectDescription
protectDescription(array $limit, array $expiry)
Call to WikiPage function for backwards compatibility.
Definition: Article.php:2692
Article\getParserOptions
getParserOptions()
Get parser options suitable for rendering the primary article wikitext.
Definition: Article.php:2208
$wgRedirectSources
$wgRedirectSources
If local interwikis are set up which allow redirects, set this regexp to restrict URLs which will be ...
Definition: DefaultSettings.php:4021
Article\updateIfNewerOn
updateIfNewerOn( $dbw, $revision)
Call to WikiPage function for backwards compatibility.
Definition: Article.php:2772
NS_MEDIAWIKI
const NS_MEDIAWIKI
Definition: Defines.php:72
$t
$t
Definition: testCompression.php:69
Article
Class for viewing MediaWiki article and history.
Definition: Article.php:38
Article\doDeleteUpdates
doDeleteUpdates( $id, Content $content=null, $revision=null, User $user=null)
Call to WikiPage function for backwards compatibility.
Definition: Article.php:2317
Article\pageDataFromTitle
pageDataFromTitle( $dbr, $title, $options=[])
Call to WikiPage function for backwards compatibility.
Definition: Article.php:2670
MediaWikiServices
injection txt This is an overview of how MediaWiki makes use of dependency injection The design described here grew from the discussion of RFC T384 The term dependency this means that anything an object needs to operate should be injected from the the object itself should only know narrow no concrete implementation of the logic it relies on The requirement to inject everything typically results in an architecture that based on two main types of and essentially stateless service objects that use other service objects to operate on the value objects As of the beginning MediaWiki is only starting to use the DI approach Much of the code still relies on global state or direct resulting in a highly cyclical dependency MediaWikiServices
Definition: injection.txt:23
$wgDebugToolbar
$wgDebugToolbar
Display the new debugging toolbar.
Definition: DefaultSettings.php:6518
Article\triggerOpportunisticLinksUpdate
triggerOpportunisticLinksUpdate(ParserOutput $parserOutput)
Call to WikiPage function for backwards compatibility.
Definition: Article.php:2756
wfMessage
either a unescaped string or a HtmlArmor object after in associative array form externallinks including delete and has completed for all link tables whether this was an auto creation use $formDescriptor instead default is conds Array Extra conditions for the No matching items in log is displayed if loglist is empty msgKey Array If you want a nice box with a set this to the key of the message First element is the message additional optional elements are parameters for the key that are processed with wfMessage() -> params() ->parseAsBlock() - offset Set to overwrite offset parameter in $wgRequest set to '' to unset offset - wrap String Wrap the message in html(usually something like "&lt
Article\getOldID
getOldID()
Definition: Article.php:326
EditPage\POST_EDIT_COOKIE_KEY_PREFIX
const POST_EDIT_COOKIE_KEY_PREFIX
Prefix of key for cookie used to pass post-edit state.
Definition: EditPage.php:201
User
The User object encapsulates all of the user-specific settings (user_id, name, rights,...
Definition: User.php:47
Article\setContext
setContext( $context)
Sets the context this Article is executed in.
Definition: Article.php:2222
Title\newFromID
static newFromID( $id, $flags=0)
Create a new Title from an article ID.
Definition: Title.php:427
Hooks\run
static run( $event, array $args=[], $deprecatedVersion=null)
Call hook functions defined in Hooks::register and $wgHooks.
Definition: Hooks.php:200
Article\insertRedirectEntry
insertRedirectEntry(Title $rt, $oldLatest=null)
Call to WikiPage function for backwards compatibility.
Definition: Article.php:2606
$wgDefaultRobotPolicy
$wgDefaultRobotPolicy
Default robot policy.
Definition: DefaultSettings.php:8024
Article\getRevisionFetched
getRevisionFetched()
Get the fetched Revision object depending on request parameters or null on failure.
Definition: Article.php:559
MWNamespace\getCanonicalName
static getCanonicalName( $index)
Returns the canonical (English) name for a given index.
Definition: MWNamespace.php:255
Article\viewRedirect
viewRedirect( $target, $appendSubtitle=true, $forceKnown=false)
Return the HTML for the top of a redirect page.
Definition: Article.php:1661
Revision\DELETED_TEXT
const DELETED_TEXT
Definition: Revision.php:47
Article\loadPageData
loadPageData( $from='fromdb')
Call to WikiPage function for backwards compatibility.
Definition: Article.php:2638
Language
Internationalisation code.
Definition: Language.php:35
Article\doEditUpdates
doEditUpdates(Revision $revision, User $user, array $options=[])
Call to WikiPage function for backwards compatibility.
Definition: Article.php:2344
Article\__set
__set( $fname, $fvalue)
Use PHP's magic __set handler to handle setting of raw WikiPage fields for backwards compatibility.
Definition: Article.php:2264
Article\showViewFooter
showViewFooter()
Show the footer section of an ordinary page view.
Definition: Article.php:1149
Revision\SlotRecord
Value object representing a content slot associated with a page revision.
Definition: SlotRecord.php:39
Article\getRedirectHeaderHtml
static getRedirectHeaderHtml(Language $lang, $target, $forceKnown=false)
Return the HTML for the top of a redirect page.
Definition: Article.php:1683
Xml\listDropDownOptions
static listDropDownOptions( $list, $params=[])
Build options for a drop-down box from a textual list.
Definition: Xml.php:541
Article\newFromTitle
static newFromTitle( $title, IContextSource $context)
Create an Article object of the appropriate class for the given page.
Definition: Article.php:160
Article\generateReason
generateReason(&$hasHistory)
Definition: Article.php:2878
Article\purgePatrolFooterCache
static purgePatrolFooterCache( $articleID)
Purge the cache used to check if it is worth showing the patrol footer For example,...
Definition: Article.php:1341
Article\doViewUpdates
doViewUpdates(User $user, $oldid=0)
Call to WikiPage function for backwards compatibility.
Definition: Article.php:2362
Article\$fetchResult
Status null $fetchResult
represents the outcome of fetchRevisionRecord().
Definition: Article.php:100
$out
this hook is for auditing only or null if authentication failed before getting that far or null if we can t even determine that probably a stub it is not rendered in wiki pages or galleries in category pages allow injecting custom HTML after the section Any uses of the hook need to handle escaping see BaseTemplate::getToolbox and BaseTemplate::makeListItem for details on the format of individual items inside of this array or by returning and letting standard HTTP rendering take place modifiable or by returning false and taking over the output $out
Definition: hooks.txt:813