MediaWiki REL1_29
Article.php
Go to the documentation of this file.
1<?php
23
35class Article implements Page {
37 protected $mContext;
38
40 protected $mPage;
41
44
49 public $mContent;
50
56
58 public $mContentLoaded = false;
59
61 public $mOldId;
62
64 public $mRedirectedFrom = null;
65
67 public $mRedirectUrl = false;
68
70 public $mRevIdFetched = 0;
71
73 public $mRevision = null;
74
77
83 public function __construct( Title $title, $oldId = null ) {
84 $this->mOldId = $oldId;
85 $this->mPage = $this->newPage( $title );
86 }
87
92 protected function newPage( Title $title ) {
93 return new WikiPage( $title );
94 }
95
101 public static function newFromID( $id ) {
102 $t = Title::newFromID( $id );
103 return $t == null ? null : new static( $t );
104 }
105
113 public static function newFromTitle( $title, IContextSource $context ) {
114 if ( NS_MEDIA == $title->getNamespace() ) {
115 // FIXME: where should this go?
116 $title = Title::makeTitle( NS_FILE, $title->getDBkey() );
117 }
118
119 $page = null;
120 Hooks::run( 'ArticleFromTitle', [ &$title, &$page, $context ] );
121 if ( !$page ) {
122 switch ( $title->getNamespace() ) {
123 case NS_FILE:
124 $page = new ImagePage( $title );
125 break;
126 case NS_CATEGORY:
127 $page = new CategoryPage( $title );
128 break;
129 default:
130 $page = new Article( $title );
131 }
132 }
133 $page->setContext( $context );
134
135 return $page;
136 }
137
146 $article = self::newFromTitle( $page->getTitle(), $context );
147 $article->mPage = $page; // override to keep process cached vars
148 return $article;
149 }
150
156 public function getRedirectedFrom() {
158 }
159
165 public function setRedirectedFrom( Title $from ) {
166 $this->mRedirectedFrom = $from;
167 }
168
174 public function getTitle() {
175 return $this->mPage->getTitle();
176 }
177
184 public function getPage() {
185 return $this->mPage;
186 }
187
191 public function clear() {
192 $this->mContentLoaded = false;
193
194 $this->mRedirectedFrom = null; # Title object if set
195 $this->mRevIdFetched = 0;
196 $this->mRedirectUrl = false;
197
198 $this->mPage->clear();
199 }
200
216 protected function getContentObject() {
217
218 if ( $this->mPage->getId() === 0 ) {
219 # If this is a MediaWiki:x message, then load the messages
220 # and return the message value for x.
221 if ( $this->getTitle()->getNamespace() == NS_MEDIAWIKI ) {
222 $text = $this->getTitle()->getDefaultMessageText();
223 if ( $text === false ) {
224 $text = '';
225 }
226
227 $content = ContentHandler::makeContent( $text, $this->getTitle() );
228 } else {
229 $message = $this->getContext()->getUser()->isLoggedIn() ? 'noarticletext' : 'noarticletextanon';
230 $content = new MessageContent( $message, null, 'parsemag' );
231 }
232 } else {
233 $this->fetchContentObject();
235 }
236
237 return $content;
238 }
239
243 public function getOldID() {
244 if ( is_null( $this->mOldId ) ) {
245 $this->mOldId = $this->getOldIDFromRequest();
246 }
247
248 return $this->mOldId;
249 }
250
256 public function getOldIDFromRequest() {
257 $this->mRedirectUrl = false;
258
259 $request = $this->getContext()->getRequest();
260 $oldid = $request->getIntOrNull( 'oldid' );
261
262 if ( $oldid === null ) {
263 return 0;
264 }
265
266 if ( $oldid !== 0 ) {
267 # Load the given revision and check whether the page is another one.
268 # In that case, update this instance to reflect the change.
269 if ( $oldid === $this->mPage->getLatest() ) {
270 $this->mRevision = $this->mPage->getRevision();
271 } else {
272 $this->mRevision = Revision::newFromId( $oldid );
273 if ( $this->mRevision !== null ) {
274 // Revision title doesn't match the page title given?
275 if ( $this->mPage->getId() != $this->mRevision->getPage() ) {
276 $function = [ get_class( $this->mPage ), 'newFromID' ];
277 $this->mPage = call_user_func( $function, $this->mRevision->getPage() );
278 }
279 }
280 }
281 }
282
283 if ( $request->getVal( 'direction' ) == 'next' ) {
284 $nextid = $this->getTitle()->getNextRevisionID( $oldid );
285 if ( $nextid ) {
286 $oldid = $nextid;
287 $this->mRevision = null;
288 } else {
289 $this->mRedirectUrl = $this->getTitle()->getFullURL( 'redirect=no' );
290 }
291 } elseif ( $request->getVal( 'direction' ) == 'prev' ) {
292 $previd = $this->getTitle()->getPreviousRevisionID( $oldid );
293 if ( $previd ) {
294 $oldid = $previd;
295 $this->mRevision = null;
296 }
297 }
298
299 return $oldid;
300 }
301
314 protected function fetchContentObject() {
315 if ( $this->mContentLoaded ) {
317 }
318
319 $this->mContentLoaded = true;
320 $this->mContent = null;
321
322 $oldid = $this->getOldID();
323
324 # Pre-fill content with error message so that if something
325 # fails we'll have something telling us what we intended.
326 // XXX: this isn't page content but a UI message. horrible.
327 $this->mContentObject = new MessageContent( 'missing-revision', [ $oldid ] );
328
329 if ( $oldid ) {
330 # $this->mRevision might already be fetched by getOldIDFromRequest()
331 if ( !$this->mRevision ) {
332 $this->mRevision = Revision::newFromId( $oldid );
333 if ( !$this->mRevision ) {
334 wfDebug( __METHOD__ . " failed to retrieve specified revision, id $oldid\n" );
335 return false;
336 }
337 }
338 } else {
339 $oldid = $this->mPage->getLatest();
340 if ( !$oldid ) {
341 wfDebug( __METHOD__ . " failed to find page data for title " .
342 $this->getTitle()->getPrefixedText() . "\n" );
343 return false;
344 }
345
346 # Update error message with correct oldid
347 $this->mContentObject = new MessageContent( 'missing-revision', [ $oldid ] );
348
349 $this->mRevision = $this->mPage->getRevision();
350
351 if ( !$this->mRevision ) {
352 wfDebug( __METHOD__ . " failed to retrieve current page, rev_id $oldid\n" );
353 return false;
354 }
355 }
356
357 // @todo FIXME: Horrible, horrible! This content-loading interface just plain sucks.
358 // We should instead work with the Revision object when we need it...
359 // Loads if user is allowed
360 $content = $this->mRevision->getContent(
362 $this->getContext()->getUser()
363 );
364
365 if ( !$content ) {
366 wfDebug( __METHOD__ . " failed to retrieve content of revision " .
367 $this->mRevision->getId() . "\n" );
368 return false;
369 }
370
371 $this->mContentObject = $content;
372 $this->mRevIdFetched = $this->mRevision->getId();
373
374 // Avoid PHP 7.1 warning of passing $this by reference
375 $articlePage = $this;
376
377 Hooks::run(
378 'ArticleAfterFetchContentObject',
379 [ &$articlePage, &$this->mContentObject ]
380 );
381
383 }
384
390 public function isCurrent() {
391 # If no oldid, this is the current version.
392 if ( $this->getOldID() == 0 ) {
393 return true;
394 }
395
396 return $this->mPage->exists() && $this->mRevision && $this->mRevision->isCurrent();
397 }
398
406 public function getRevisionFetched() {
407 $this->fetchContentObject();
408
409 return $this->mRevision;
410 }
411
417 public function getRevIdFetched() {
418 if ( $this->mRevIdFetched ) {
420 } else {
421 return $this->mPage->getLatest();
422 }
423 }
424
429 public function view() {
431
432 # Get variables from query string
433 # As side effect this will load the revision and update the title
434 # in a revision ID is passed in the request, so this should remain
435 # the first call of this method even if $oldid is used way below.
436 $oldid = $this->getOldID();
437
438 $user = $this->getContext()->getUser();
439 # Another whitelist check in case getOldID() is altering the title
440 $permErrors = $this->getTitle()->getUserPermissionsErrors( 'read', $user );
441 if ( count( $permErrors ) ) {
442 wfDebug( __METHOD__ . ": denied on secondary read check\n" );
443 throw new PermissionsError( 'read', $permErrors );
444 }
445
446 $outputPage = $this->getContext()->getOutput();
447 # getOldID() may as well want us to redirect somewhere else
448 if ( $this->mRedirectUrl ) {
449 $outputPage->redirect( $this->mRedirectUrl );
450 wfDebug( __METHOD__ . ": redirecting due to oldid\n" );
451
452 return;
453 }
454
455 # If we got diff in the query, we want to see a diff page instead of the article.
456 if ( $this->getContext()->getRequest()->getCheck( 'diff' ) ) {
457 wfDebug( __METHOD__ . ": showing diff page\n" );
458 $this->showDiffPage();
459
460 return;
461 }
462
463 # Set page title (may be overridden by DISPLAYTITLE)
464 $outputPage->setPageTitle( $this->getTitle()->getPrefixedText() );
465
466 $outputPage->setArticleFlag( true );
467 # Allow frames by default
468 $outputPage->allowClickjacking();
469
470 $parserCache = ParserCache::singleton();
471
472 $parserOptions = $this->getParserOptions();
473 # Render printable version, use printable version cache
474 if ( $outputPage->isPrintable() ) {
475 $parserOptions->setIsPrintable( true );
476 $parserOptions->setEditSection( false );
477 } elseif ( !$this->isCurrent() || !$this->getTitle()->quickUserCan( 'edit', $user ) ) {
478 $parserOptions->setEditSection( false );
479 }
480
481 # Try client and file cache
482 if ( !$wgDebugToolbar && $oldid === 0 && $this->mPage->checkTouched() ) {
483 # Try to stream the output from file cache
484 if ( $wgUseFileCache && $this->tryFileCache() ) {
485 wfDebug( __METHOD__ . ": done file cache\n" );
486 # tell wgOut that output is taken care of
487 $outputPage->disable();
488 $this->mPage->doViewUpdates( $user, $oldid );
489
490 return;
491 }
492 }
493
494 # Should the parser cache be used?
495 $useParserCache = $this->mPage->shouldCheckParserCache( $parserOptions, $oldid );
496 wfDebug( 'Article::view using parser cache: ' . ( $useParserCache ? 'yes' : 'no' ) . "\n" );
497 if ( $user->getStubThreshold() ) {
498 MediaWikiServices::getInstance()->getStatsdDataFactory()->increment( 'pcache_miss_stub' );
499 }
500
502 $this->showNamespaceHeader();
503
504 # Iterate through the possible ways of constructing the output text.
505 # Keep going until $outputDone is set, or we run out of things to do.
506 $pass = 0;
507 $outputDone = false;
508 $this->mParserOutput = false;
509
510 while ( !$outputDone && ++$pass ) {
511 switch ( $pass ) {
512 case 1:
513 // Avoid PHP 7.1 warning of passing $this by reference
514 $articlePage = $this;
515 Hooks::run( 'ArticleViewHeader', [ &$articlePage, &$outputDone, &$useParserCache ] );
516 break;
517 case 2:
518 # Early abort if the page doesn't exist
519 if ( !$this->mPage->exists() ) {
520 wfDebug( __METHOD__ . ": showing missing article\n" );
521 $this->showMissingArticle();
522 $this->mPage->doViewUpdates( $user );
523 return;
524 }
525
526 # Try the parser cache
527 if ( $useParserCache ) {
528 $this->mParserOutput = $parserCache->get( $this->mPage, $parserOptions );
529
530 if ( $this->mParserOutput !== false ) {
531 if ( $oldid ) {
532 wfDebug( __METHOD__ . ": showing parser cache contents for current rev permalink\n" );
533 $this->setOldSubtitle( $oldid );
534 } else {
535 wfDebug( __METHOD__ . ": showing parser cache contents\n" );
536 }
537 $outputPage->addParserOutput( $this->mParserOutput );
538 # Ensure that UI elements requiring revision ID have
539 # the correct version information.
540 $outputPage->setRevisionId( $this->mPage->getLatest() );
541 # Preload timestamp to avoid a DB hit
542 $cachedTimestamp = $this->mParserOutput->getTimestamp();
543 if ( $cachedTimestamp !== null ) {
544 $outputPage->setRevisionTimestamp( $cachedTimestamp );
545 $this->mPage->setTimestamp( $cachedTimestamp );
546 }
547 $outputDone = true;
548 }
549 }
550 break;
551 case 3:
552 # This will set $this->mRevision if needed
553 $this->fetchContentObject();
554
555 # Are we looking at an old revision
556 if ( $oldid && $this->mRevision ) {
557 $this->setOldSubtitle( $oldid );
558
559 if ( !$this->showDeletedRevisionHeader() ) {
560 wfDebug( __METHOD__ . ": cannot view deleted revision\n" );
561 return;
562 }
563 }
564
565 # Ensure that UI elements requiring revision ID have
566 # the correct version information.
567 $outputPage->setRevisionId( $this->getRevIdFetched() );
568 # Preload timestamp to avoid a DB hit
569 $outputPage->setRevisionTimestamp( $this->mPage->getTimestamp() );
570
571 if ( !Hooks::run( 'ArticleContentViewCustom',
572 [ $this->fetchContentObject(), $this->getTitle(), $outputPage ] ) ) {
573
574 # Allow extensions do their own custom view for certain pages
575 $outputDone = true;
576 }
577 break;
578 case 4:
579 # Run the parse, protected by a pool counter
580 wfDebug( __METHOD__ . ": doing uncached parse\n" );
581
582 $content = $this->getContentObject();
583 $poolArticleView = new PoolWorkArticleView( $this->getPage(), $parserOptions,
584 $this->getRevIdFetched(), $useParserCache, $content );
585
586 if ( !$poolArticleView->execute() ) {
587 $error = $poolArticleView->getError();
588 if ( $error ) {
589 $outputPage->clearHTML(); // for release() errors
590 $outputPage->enableClientCache( false );
591 $outputPage->setRobotPolicy( 'noindex,nofollow' );
592
593 $errortext = $error->getWikiText( false, 'view-pool-error' );
594 $outputPage->addWikiText( '<div class="errorbox">' . $errortext . '</div>' );
595 }
596 # Connection or timeout error
597 return;
598 }
599
600 $this->mParserOutput = $poolArticleView->getParserOutput();
601 $outputPage->addParserOutput( $this->mParserOutput );
602 if ( $content->getRedirectTarget() ) {
603 $outputPage->addSubtitle( "<span id=\"redirectsub\">" .
604 $this->getContext()->msg( 'redirectpagesub' )->parse() . "</span>" );
605 }
606
607 # Don't cache a dirty ParserOutput object
608 if ( $poolArticleView->getIsDirty() ) {
609 $outputPage->setCdnMaxage( 0 );
610 $outputPage->addHTML( "<!-- parser cache is expired, " .
611 "sending anyway due to pool overload-->\n" );
612 }
613
614 $outputDone = true;
615 break;
616 # Should be unreachable, but just in case...
617 default:
618 break 2;
619 }
620 }
621
622 # Get the ParserOutput actually *displayed* here.
623 # Note that $this->mParserOutput is the *current*/oldid version output.
624 $pOutput = ( $outputDone instanceof ParserOutput )
625 ? $outputDone // object fetched by hook
627
628 # Adjust title for main page & pages with displaytitle
629 if ( $pOutput ) {
630 $this->adjustDisplayTitle( $pOutput );
631 }
632
633 # For the main page, overwrite the <title> element with the con-
634 # tents of 'pagetitle-view-mainpage' instead of the default (if
635 # that's not empty).
636 # This message always exists because it is in the i18n files
637 if ( $this->getTitle()->isMainPage() ) {
638 $msg = wfMessage( 'pagetitle-view-mainpage' )->inContentLanguage();
639 if ( !$msg->isDisabled() ) {
640 $outputPage->setHTMLTitle( $msg->title( $this->getTitle() )->text() );
641 }
642 }
643
644 # Use adaptive TTLs for CDN so delayed/failed purges are noticed less often.
645 # This could use getTouched(), but that could be scary for major template edits.
646 $outputPage->adaptCdnTTL( $this->mPage->getTimestamp(), IExpiringStore::TTL_DAY );
647
648 # Check for any __NOINDEX__ tags on the page using $pOutput
649 $policy = $this->getRobotPolicy( 'view', $pOutput );
650 $outputPage->setIndexPolicy( $policy['index'] );
651 $outputPage->setFollowPolicy( $policy['follow'] );
652
653 $this->showViewFooter();
654 $this->mPage->doViewUpdates( $user, $oldid );
655
656 $outputPage->addModules( 'mediawiki.action.view.postEdit' );
657 }
658
663 public function adjustDisplayTitle( ParserOutput $pOutput ) {
664 # Adjust the title if it was set by displaytitle, -{T|}- or language conversion
665 $titleText = $pOutput->getTitleText();
666 if ( strval( $titleText ) !== '' ) {
667 $this->getContext()->getOutput()->setPageTitle( $titleText );
668 }
669 }
670
675 protected function showDiffPage() {
676 $request = $this->getContext()->getRequest();
677 $user = $this->getContext()->getUser();
678 $diff = $request->getVal( 'diff' );
679 $rcid = $request->getVal( 'rcid' );
680 $diffOnly = $request->getBool( 'diffonly', $user->getOption( 'diffonly' ) );
681 $purge = $request->getVal( 'action' ) == 'purge';
682 $unhide = $request->getInt( 'unhide' ) == 1;
683 $oldid = $this->getOldID();
684
685 $rev = $this->getRevisionFetched();
686
687 if ( !$rev ) {
688 $this->getContext()->getOutput()->setPageTitle( wfMessage( 'errorpagetitle' ) );
689 $msg = $this->getContext()->msg( 'difference-missing-revision' )
690 ->params( $oldid )
691 ->numParams( 1 )
692 ->parseAsBlock();
693 $this->getContext()->getOutput()->addHTML( $msg );
694 return;
695 }
696
697 $contentHandler = $rev->getContentHandler();
698 $de = $contentHandler->createDifferenceEngine(
699 $this->getContext(),
700 $oldid,
701 $diff,
702 $rcid,
703 $purge,
704 $unhide
705 );
706
707 // DifferenceEngine directly fetched the revision:
708 $this->mRevIdFetched = $de->mNewid;
709 $de->showDiffPage( $diffOnly );
710
711 // Run view updates for the newer revision being diffed (and shown
712 // below the diff if not $diffOnly).
713 list( $old, $new ) = $de->mapDiffPrevNext( $oldid, $diff );
714 // New can be false, convert it to 0 - this conveniently means the latest revision
715 $this->mPage->doViewUpdates( $user, (int)$new );
716 }
717
725 public function getRobotPolicy( $action, $pOutput = null ) {
727
728 $ns = $this->getTitle()->getNamespace();
729
730 # Don't index user and user talk pages for blocked users (T13443)
731 if ( ( $ns == NS_USER || $ns == NS_USER_TALK ) && !$this->getTitle()->isSubpage() ) {
732 $specificTarget = null;
733 $vagueTarget = null;
734 $titleText = $this->getTitle()->getText();
735 if ( IP::isValid( $titleText ) ) {
736 $vagueTarget = $titleText;
737 } else {
738 $specificTarget = $titleText;
739 }
740 if ( Block::newFromTarget( $specificTarget, $vagueTarget ) instanceof Block ) {
741 return [
742 'index' => 'noindex',
743 'follow' => 'nofollow'
744 ];
745 }
746 }
747
748 if ( $this->mPage->getId() === 0 || $this->getOldID() ) {
749 # Non-articles (special pages etc), and old revisions
750 return [
751 'index' => 'noindex',
752 'follow' => 'nofollow'
753 ];
754 } elseif ( $this->getContext()->getOutput()->isPrintable() ) {
755 # Discourage indexing of printable versions, but encourage following
756 return [
757 'index' => 'noindex',
758 'follow' => 'follow'
759 ];
760 } elseif ( $this->getContext()->getRequest()->getInt( 'curid' ) ) {
761 # For ?curid=x urls, disallow indexing
762 return [
763 'index' => 'noindex',
764 'follow' => 'follow'
765 ];
766 }
767
768 # Otherwise, construct the policy based on the various config variables.
770
771 if ( isset( $wgNamespaceRobotPolicies[$ns] ) ) {
772 # Honour customised robot policies for this namespace
773 $policy = array_merge(
774 $policy,
775 self::formatRobotPolicy( $wgNamespaceRobotPolicies[$ns] )
776 );
777 }
778 if ( $this->getTitle()->canUseNoindex() && is_object( $pOutput ) && $pOutput->getIndexPolicy() ) {
779 # __INDEX__ and __NOINDEX__ magic words, if allowed. Incorporates
780 # a final sanity check that we have really got the parser output.
781 $policy = array_merge(
782 $policy,
783 [ 'index' => $pOutput->getIndexPolicy() ]
784 );
785 }
786
787 if ( isset( $wgArticleRobotPolicies[$this->getTitle()->getPrefixedText()] ) ) {
788 # (T16900) site config can override user-defined __INDEX__ or __NOINDEX__
789 $policy = array_merge(
790 $policy,
791 self::formatRobotPolicy( $wgArticleRobotPolicies[$this->getTitle()->getPrefixedText()] )
792 );
793 }
794
795 return $policy;
796 }
797
805 public static function formatRobotPolicy( $policy ) {
806 if ( is_array( $policy ) ) {
807 return $policy;
808 } elseif ( !$policy ) {
809 return [];
810 }
811
812 $policy = explode( ',', $policy );
813 $policy = array_map( 'trim', $policy );
814
815 $arr = [];
816 foreach ( $policy as $var ) {
817 if ( in_array( $var, [ 'index', 'noindex' ] ) ) {
818 $arr['index'] = $var;
819 } elseif ( in_array( $var, [ 'follow', 'nofollow' ] ) ) {
820 $arr['follow'] = $var;
821 }
822 }
823
824 return $arr;
825 }
826
834 public function showRedirectedFromHeader() {
836
837 $context = $this->getContext();
838 $outputPage = $context->getOutput();
840 $rdfrom = $request->getVal( 'rdfrom' );
841
842 // Construct a URL for the current page view, but with the target title
843 $query = $request->getValues();
844 unset( $query['rdfrom'] );
845 unset( $query['title'] );
846 if ( $this->getTitle()->isRedirect() ) {
847 // Prevent double redirects
848 $query['redirect'] = 'no';
849 }
850 $redirectTargetUrl = $this->getTitle()->getLinkURL( $query );
851
852 if ( isset( $this->mRedirectedFrom ) ) {
853 // Avoid PHP 7.1 warning of passing $this by reference
854 $articlePage = $this;
855
856 // This is an internally redirected page view.
857 // We'll need a backlink to the source page for navigation.
858 if ( Hooks::run( 'ArticleViewRedirect', [ &$articlePage ] ) ) {
859 $redir = Linker::linkKnown(
860 $this->mRedirectedFrom,
861 null,
862 [],
863 [ 'redirect' => 'no' ]
864 );
865
866 $outputPage->addSubtitle( "<span class=\"mw-redirectedfrom\">" .
867 $context->msg( 'redirectedfrom' )->rawParams( $redir )->parse()
868 . "</span>" );
869
870 // Add the script to update the displayed URL and
871 // set the fragment if one was specified in the redirect
872 $outputPage->addJsConfigVars( [
873 'wgInternalRedirectTargetUrl' => $redirectTargetUrl,
874 ] );
875 $outputPage->addModules( 'mediawiki.action.view.redirect' );
876
877 // Add a <link rel="canonical"> tag
878 $outputPage->setCanonicalUrl( $this->getTitle()->getCanonicalURL() );
879
880 // Tell the output object that the user arrived at this article through a redirect
881 $outputPage->setRedirectedFrom( $this->mRedirectedFrom );
882
883 return true;
884 }
885 } elseif ( $rdfrom ) {
886 // This is an externally redirected view, from some other wiki.
887 // If it was reported from a trusted site, supply a backlink.
888 if ( $wgRedirectSources && preg_match( $wgRedirectSources, $rdfrom ) ) {
889 $redir = Linker::makeExternalLink( $rdfrom, $rdfrom );
890 $outputPage->addSubtitle( "<span class=\"mw-redirectedfrom\">" .
891 $context->msg( 'redirectedfrom' )->rawParams( $redir )->parse()
892 . "</span>" );
893
894 // Add the script to update the displayed URL
895 $outputPage->addJsConfigVars( [
896 'wgInternalRedirectTargetUrl' => $redirectTargetUrl,
897 ] );
898 $outputPage->addModules( 'mediawiki.action.view.redirect' );
899
900 return true;
901 }
902 }
903
904 return false;
905 }
906
911 public function showNamespaceHeader() {
912 if ( $this->getTitle()->isTalkPage() ) {
913 if ( !wfMessage( 'talkpageheader' )->isDisabled() ) {
914 $this->getContext()->getOutput()->wrapWikiMsg(
915 "<div class=\"mw-talkpageheader\">\n$1\n</div>",
916 [ 'talkpageheader' ]
917 );
918 }
919 }
920 }
921
925 public function showViewFooter() {
926 # check if we're displaying a [[User talk:x.x.x.x]] anonymous talk page
927 if ( $this->getTitle()->getNamespace() == NS_USER_TALK
928 && IP::isValid( $this->getTitle()->getText() )
929 ) {
930 $this->getContext()->getOutput()->addWikiMsg( 'anontalkpagetext' );
931 }
932
933 // Show a footer allowing the user to patrol the shown revision or page if possible
934 $patrolFooterShown = $this->showPatrolFooter();
935
936 Hooks::run( 'ArticleViewFooter', [ $this, $patrolFooterShown ] );
937 }
938
948 public function showPatrolFooter() {
950
951 $outputPage = $this->getContext()->getOutput();
952 $user = $this->getContext()->getUser();
953 $title = $this->getTitle();
954 $rc = false;
955
956 if ( !$title->quickUserCan( 'patrol', $user )
958 || ( $wgUseFilePatrol && $title->inNamespace( NS_FILE ) ) )
959 ) {
960 // Patrolling is disabled or the user isn't allowed to
961 return false;
962 }
963
964 if ( $this->mRevision
965 && !RecentChange::isInRCLifespan( $this->mRevision->getTimestamp(), 21600 )
966 ) {
967 // The current revision is already older than what could be in the RC table
968 // 6h tolerance because the RC might not be cleaned out regularly
969 return false;
970 }
971
972 // Check for cached results
973 $key = wfMemcKey( 'unpatrollable-page', $title->getArticleID() );
974 $cache = ObjectCache::getMainWANInstance();
975 if ( $cache->get( $key ) ) {
976 return false;
977 }
978
980 $oldestRevisionTimestamp = $dbr->selectField(
981 'revision',
982 'MIN( rev_timestamp )',
983 [ 'rev_page' => $title->getArticleID() ],
984 __METHOD__
985 );
986
987 // New page patrol: Get the timestamp of the oldest revison which
988 // the revision table holds for the given page. Then we look
989 // whether it's within the RC lifespan and if it is, we try
990 // to get the recentchanges row belonging to that entry
991 // (with rc_new = 1).
992 $recentPageCreation = false;
993 if ( $oldestRevisionTimestamp
994 && RecentChange::isInRCLifespan( $oldestRevisionTimestamp, 21600 )
995 ) {
996 // 6h tolerance because the RC might not be cleaned out regularly
997 $recentPageCreation = true;
999 [
1000 'rc_new' => 1,
1001 'rc_timestamp' => $oldestRevisionTimestamp,
1002 'rc_namespace' => $title->getNamespace(),
1003 'rc_cur_id' => $title->getArticleID()
1004 ],
1005 __METHOD__
1006 );
1007 if ( $rc ) {
1008 // Use generic patrol message for new pages
1009 $markPatrolledMsg = wfMessage( 'markaspatrolledtext' );
1010 }
1011 }
1012
1013 // File patrol: Get the timestamp of the latest upload for this page,
1014 // check whether it is within the RC lifespan and if it is, we try
1015 // to get the recentchanges row belonging to that entry
1016 // (with rc_type = RC_LOG, rc_log_type = upload).
1017 $recentFileUpload = false;
1018 if ( ( !$rc || $rc->getAttribute( 'rc_patrolled' ) ) && $wgUseFilePatrol
1019 && $title->getNamespace() === NS_FILE ) {
1020 // Retrieve timestamp of most recent upload
1021 $newestUploadTimestamp = $dbr->selectField(
1022 'image',
1023 'MAX( img_timestamp )',
1024 [ 'img_name' => $title->getDBkey() ],
1025 __METHOD__
1026 );
1027 if ( $newestUploadTimestamp
1028 && RecentChange::isInRCLifespan( $newestUploadTimestamp, 21600 )
1029 ) {
1030 // 6h tolerance because the RC might not be cleaned out regularly
1031 $recentFileUpload = true;
1033 [
1034 'rc_type' => RC_LOG,
1035 'rc_log_type' => 'upload',
1036 'rc_timestamp' => $newestUploadTimestamp,
1037 'rc_namespace' => NS_FILE,
1038 'rc_cur_id' => $title->getArticleID()
1039 ],
1040 __METHOD__
1041 );
1042 if ( $rc ) {
1043 // Use patrol message specific to files
1044 $markPatrolledMsg = wfMessage( 'markaspatrolledtext-file' );
1045 }
1046 }
1047 }
1048
1049 if ( !$recentPageCreation && !$recentFileUpload ) {
1050 // Page creation and latest upload (for files) is too old to be in RC
1051
1052 // We definitely can't patrol so cache the information
1053 // When a new file version is uploaded, the cache is cleared
1054 $cache->set( $key, '1' );
1055
1056 return false;
1057 }
1058
1059 if ( !$rc ) {
1060 // Don't cache: This can be hit if the page gets accessed very fast after
1061 // its creation / latest upload or in case we have high replica DB lag. In case
1062 // the revision is too old, we will already return above.
1063 return false;
1064 }
1065
1066 if ( $rc->getAttribute( 'rc_patrolled' ) ) {
1067 // Patrolled RC entry around
1068
1069 // Cache the information we gathered above in case we can't patrol
1070 // Don't cache in case we can patrol as this could change
1071 $cache->set( $key, '1' );
1072
1073 return false;
1074 }
1075
1076 if ( $rc->getPerformer()->equals( $user ) ) {
1077 // Don't show a patrol link for own creations/uploads. If the user could
1078 // patrol them, they already would be patrolled
1079 return false;
1080 }
1081
1082 $outputPage->preventClickjacking();
1083 if ( $wgEnableAPI && $wgEnableWriteAPI && $user->isAllowed( 'writeapi' ) ) {
1084 $outputPage->addModules( 'mediawiki.page.patrol.ajax' );
1085 }
1086
1088 $title,
1089 $markPatrolledMsg->escaped(),
1090 [],
1091 [
1092 'action' => 'markpatrolled',
1093 'rcid' => $rc->getAttribute( 'rc_id' ),
1094 ]
1095 );
1096
1097 $outputPage->addHTML(
1098 "<div class='patrollink' data-mw='interface'>" .
1099 wfMessage( 'markaspatrolledlink' )->rawParams( $link )->escaped() .
1100 '</div>'
1101 );
1102
1103 return true;
1104 }
1105
1112 public static function purgePatrolFooterCache( $articleID ) {
1113 $cache = ObjectCache::getMainWANInstance();
1114 $cache->delete( wfMemcKey( 'unpatrollable-page', $articleID ) );
1115 }
1116
1121 public function showMissingArticle() {
1123
1124 $outputPage = $this->getContext()->getOutput();
1125 // Whether the page is a root user page of an existing user (but not a subpage)
1126 $validUserPage = false;
1127
1128 $title = $this->getTitle();
1129
1130 # Show info in user (talk) namespace. Does the user exist? Is he blocked?
1131 if ( $title->getNamespace() == NS_USER
1132 || $title->getNamespace() == NS_USER_TALK
1133 ) {
1134 $rootPart = explode( '/', $title->getText() )[0];
1135 $user = User::newFromName( $rootPart, false /* allow IP users */ );
1136 $ip = User::isIP( $rootPart );
1137 $block = Block::newFromTarget( $user, $user );
1138
1139 if ( !( $user && $user->isLoggedIn() ) && !$ip ) { # User does not exist
1140 $outputPage->wrapWikiMsg( "<div class=\"mw-userpage-userdoesnotexist error\">\n\$1\n</div>",
1141 [ 'userpage-userdoesnotexist-view', wfEscapeWikiText( $rootPart ) ] );
1142 } elseif ( !is_null( $block ) && $block->getType() != Block::TYPE_AUTO ) {
1143 # Show log extract if the user is currently blocked
1145 $outputPage,
1146 'block',
1147 MWNamespace::getCanonicalName( NS_USER ) . ':' . $block->getTarget(),
1148 '',
1149 [
1150 'lim' => 1,
1151 'showIfEmpty' => false,
1152 'msgKey' => [
1153 'blocked-notice-logextract',
1154 $user->getName() # Support GENDER in notice
1155 ]
1156 ]
1157 );
1158 $validUserPage = !$title->isSubpage();
1159 } else {
1160 $validUserPage = !$title->isSubpage();
1161 }
1162 }
1163
1164 Hooks::run( 'ShowMissingArticle', [ $this ] );
1165
1166 # Show delete and move logs if there were any such events.
1167 # The logging query can DOS the site when bots/crawlers cause 404 floods,
1168 # so be careful showing this. 404 pages must be cheap as they are hard to cache.
1169 $cache = ObjectCache::getMainStashInstance();
1170 $key = wfMemcKey( 'page-recent-delete', md5( $title->getPrefixedText() ) );
1171 $loggedIn = $this->getContext()->getUser()->isLoggedIn();
1172 if ( $loggedIn || $cache->get( $key ) ) {
1173 $logTypes = [ 'delete', 'move' ];
1174
1175 $dbr = wfGetDB( DB_REPLICA );
1176
1177 $conds = [ 'log_action != ' . $dbr->addQuotes( 'revision' ) ];
1178 // Give extensions a chance to hide their (unrelated) log entries
1179 Hooks::run( 'Article::MissingArticleConditions', [ &$conds, $logTypes ] );
1181 $outputPage,
1182 $logTypes,
1183 $title,
1184 '',
1185 [
1186 'lim' => 10,
1187 'conds' => $conds,
1188 'showIfEmpty' => false,
1189 'msgKey' => [ $loggedIn
1190 ? 'moveddeleted-notice'
1191 : 'moveddeleted-notice-recent'
1192 ]
1193 ]
1194 );
1195 }
1196
1197 if ( !$this->mPage->hasViewableContent() && $wgSend404Code && !$validUserPage ) {
1198 // If there's no backing content, send a 404 Not Found
1199 // for better machine handling of broken links.
1200 $this->getContext()->getRequest()->response()->statusHeader( 404 );
1201 }
1202
1203 // Also apply the robot policy for nonexisting pages (even if a 404 was used for sanity)
1204 $policy = $this->getRobotPolicy( 'view' );
1205 $outputPage->setIndexPolicy( $policy['index'] );
1206 $outputPage->setFollowPolicy( $policy['follow'] );
1207
1208 $hookResult = Hooks::run( 'BeforeDisplayNoArticleText', [ $this ] );
1209
1210 if ( !$hookResult ) {
1211 return;
1212 }
1213
1214 # Show error message
1215 $oldid = $this->getOldID();
1216 if ( !$oldid && $title->getNamespace() === NS_MEDIAWIKI && $title->hasSourceText() ) {
1217 $outputPage->addParserOutput( $this->getContentObject()->getParserOutput( $title ) );
1218 } else {
1219 if ( $oldid ) {
1220 $text = wfMessage( 'missing-revision', $oldid )->plain();
1221 } elseif ( $title->quickUserCan( 'create', $this->getContext()->getUser() )
1222 && $title->quickUserCan( 'edit', $this->getContext()->getUser() )
1223 ) {
1224 $message = $this->getContext()->getUser()->isLoggedIn() ? 'noarticletext' : 'noarticletextanon';
1225 $text = wfMessage( $message )->plain();
1226 } else {
1227 $text = wfMessage( 'noarticletext-nopermission' )->plain();
1228 }
1229
1230 $dir = $this->getContext()->getLanguage()->getDir();
1231 $lang = $this->getContext()->getLanguage()->getCode();
1232 $outputPage->addWikiText( Xml::openElement( 'div', [
1233 'class' => "noarticletext mw-content-$dir",
1234 'dir' => $dir,
1235 'lang' => $lang,
1236 ] ) . "\n$text\n</div>" );
1237 }
1238 }
1239
1246 public function showDeletedRevisionHeader() {
1247 if ( !$this->mRevision->isDeleted( Revision::DELETED_TEXT ) ) {
1248 // Not deleted
1249 return true;
1250 }
1251
1252 $outputPage = $this->getContext()->getOutput();
1253 $user = $this->getContext()->getUser();
1254 // If the user is not allowed to see it...
1255 if ( !$this->mRevision->userCan( Revision::DELETED_TEXT, $user ) ) {
1256 $outputPage->wrapWikiMsg( "<div class='mw-warning plainlinks'>\n$1\n</div>\n",
1257 'rev-deleted-text-permission' );
1258
1259 return false;
1260 // If the user needs to confirm that they want to see it...
1261 } elseif ( $this->getContext()->getRequest()->getInt( 'unhide' ) != 1 ) {
1262 # Give explanation and add a link to view the revision...
1263 $oldid = intval( $this->getOldID() );
1264 $link = $this->getTitle()->getFullURL( "oldid={$oldid}&unhide=1" );
1265 $msg = $this->mRevision->isDeleted( Revision::DELETED_RESTRICTED ) ?
1266 'rev-suppressed-text-unhide' : 'rev-deleted-text-unhide';
1267 $outputPage->wrapWikiMsg( "<div class='mw-warning plainlinks'>\n$1\n</div>\n",
1268 [ $msg, $link ] );
1269
1270 return false;
1271 // We are allowed to see...
1272 } else {
1273 $msg = $this->mRevision->isDeleted( Revision::DELETED_RESTRICTED ) ?
1274 'rev-suppressed-text-view' : 'rev-deleted-text-view';
1275 $outputPage->wrapWikiMsg( "<div class='mw-warning plainlinks'>\n$1\n</div>\n", $msg );
1276
1277 return true;
1278 }
1279 }
1280
1289 public function setOldSubtitle( $oldid = 0 ) {
1290 // Avoid PHP 7.1 warning of passing $this by reference
1291 $articlePage = $this;
1292
1293 if ( !Hooks::run( 'DisplayOldSubtitle', [ &$articlePage, &$oldid ] ) ) {
1294 return;
1295 }
1296
1297 $context = $this->getContext();
1298 $unhide = $context->getRequest()->getInt( 'unhide' ) == 1;
1299
1300 # Cascade unhide param in links for easy deletion browsing
1301 $extraParams = [];
1302 if ( $unhide ) {
1303 $extraParams['unhide'] = 1;
1304 }
1305
1306 if ( $this->mRevision && $this->mRevision->getId() === $oldid ) {
1307 $revision = $this->mRevision;
1308 } else {
1309 $revision = Revision::newFromId( $oldid );
1310 }
1311
1312 $timestamp = $revision->getTimestamp();
1313
1314 $current = ( $oldid == $this->mPage->getLatest() );
1315 $language = $context->getLanguage();
1316 $user = $context->getUser();
1317
1318 $td = $language->userTimeAndDate( $timestamp, $user );
1319 $tddate = $language->userDate( $timestamp, $user );
1320 $tdtime = $language->userTime( $timestamp, $user );
1321
1322 # Show user links if allowed to see them. If hidden, then show them only if requested...
1323 $userlinks = Linker::revUserTools( $revision, !$unhide );
1324
1325 $infomsg = $current && !$context->msg( 'revision-info-current' )->isDisabled()
1326 ? 'revision-info-current'
1327 : 'revision-info';
1328
1329 $outputPage = $context->getOutput();
1330 $revisionInfo = "<div id=\"mw-{$infomsg}\">" .
1331 $context->msg( $infomsg, $td )
1332 ->rawParams( $userlinks )
1333 ->params( $revision->getId(), $tddate, $tdtime, $revision->getUserText() )
1334 ->rawParams( Linker::revComment( $revision, true, true ) )
1335 ->parse() .
1336 "</div>";
1337
1338 $lnk = $current
1339 ? $context->msg( 'currentrevisionlink' )->escaped()
1341 $this->getTitle(),
1342 $context->msg( 'currentrevisionlink' )->escaped(),
1343 [],
1344 $extraParams
1345 );
1346 $curdiff = $current
1347 ? $context->msg( 'diff' )->escaped()
1349 $this->getTitle(),
1350 $context->msg( 'diff' )->escaped(),
1351 [],
1352 [
1353 'diff' => 'cur',
1354 'oldid' => $oldid
1355 ] + $extraParams
1356 );
1357 $prev = $this->getTitle()->getPreviousRevisionID( $oldid );
1358 $prevlink = $prev
1360 $this->getTitle(),
1361 $context->msg( 'previousrevision' )->escaped(),
1362 [],
1363 [
1364 'direction' => 'prev',
1365 'oldid' => $oldid
1366 ] + $extraParams
1367 )
1368 : $context->msg( 'previousrevision' )->escaped();
1369 $prevdiff = $prev
1371 $this->getTitle(),
1372 $context->msg( 'diff' )->escaped(),
1373 [],
1374 [
1375 'diff' => 'prev',
1376 'oldid' => $oldid
1377 ] + $extraParams
1378 )
1379 : $context->msg( 'diff' )->escaped();
1380 $nextlink = $current
1381 ? $context->msg( 'nextrevision' )->escaped()
1383 $this->getTitle(),
1384 $context->msg( 'nextrevision' )->escaped(),
1385 [],
1386 [
1387 'direction' => 'next',
1388 'oldid' => $oldid
1389 ] + $extraParams
1390 );
1391 $nextdiff = $current
1392 ? $context->msg( 'diff' )->escaped()
1394 $this->getTitle(),
1395 $context->msg( 'diff' )->escaped(),
1396 [],
1397 [
1398 'diff' => 'next',
1399 'oldid' => $oldid
1400 ] + $extraParams
1401 );
1402
1403 $cdel = Linker::getRevDeleteLink( $user, $revision, $this->getTitle() );
1404 if ( $cdel !== '' ) {
1405 $cdel .= ' ';
1406 }
1407
1408 // the outer div is need for styling the revision info and nav in MobileFrontend
1409 $outputPage->addSubtitle( "<div class=\"mw-revision\">" . $revisionInfo .
1410 "<div id=\"mw-revision-nav\">" . $cdel .
1411 $context->msg( 'revision-nav' )->rawParams(
1412 $prevdiff, $prevlink, $lnk, $curdiff, $nextlink, $nextdiff
1413 )->escaped() . "</div></div>" );
1414 }
1415
1427 public function viewRedirect( $target, $appendSubtitle = true, $forceKnown = false ) {
1428 $lang = $this->getTitle()->getPageLanguage();
1429 $out = $this->getContext()->getOutput();
1430 if ( $appendSubtitle ) {
1431 $out->addSubtitle( wfMessage( 'redirectpagesub' ) );
1432 }
1433 $out->addModuleStyles( 'mediawiki.action.view.redirectPage' );
1434 return static::getRedirectHeaderHtml( $lang, $target, $forceKnown );
1435 }
1436
1449 public static function getRedirectHeaderHtml( Language $lang, $target, $forceKnown = false ) {
1450 if ( !is_array( $target ) ) {
1451 $target = [ $target ];
1452 }
1453
1454 $html = '<ul class="redirectText">';
1456 foreach ( $target as $title ) {
1457 $html .= '<li>' . Linker::link(
1458 $title,
1459 htmlspecialchars( $title->getFullText() ),
1460 [],
1461 // Make sure wiki page redirects are not followed
1462 $title->isRedirect() ? [ 'redirect' => 'no' ] : [],
1463 ( $forceKnown ? [ 'known', 'noclasses' ] : [] )
1464 ) . '</li>';
1465 }
1466 $html .= '</ul>';
1467
1468 $redirectToText = wfMessage( 'redirectto' )->inLanguage( $lang )->escaped();
1469
1470 return '<div class="redirectMsg">' .
1471 '<p>' . $redirectToText . '</p>' .
1472 $html .
1473 '</div>';
1474 }
1475
1484 public function addHelpLink( $to, $overrideBaseUrl = false ) {
1485 $msg = wfMessage(
1486 'namespace-' . $this->getTitle()->getNamespace() . '-helppage'
1487 );
1488
1489 $out = $this->getContext()->getOutput();
1490 if ( !$msg->isDisabled() ) {
1491 $helpUrl = Skin::makeUrl( $msg->plain() );
1492 $out->addHelpLink( $helpUrl, true );
1493 } else {
1494 $out->addHelpLink( $to, $overrideBaseUrl );
1495 }
1496 }
1497
1501 public function render() {
1502 $this->getContext()->getRequest()->response()->header( 'X-Robots-Tag: noindex' );
1503 $this->getContext()->getOutput()->setArticleBodyOnly( true );
1504 $this->getContext()->getOutput()->enableSectionEditLinks( false );
1505 $this->view();
1506 }
1507
1511 public function protect() {
1512 $form = new ProtectionForm( $this );
1513 $form->execute();
1514 }
1515
1519 public function unprotect() {
1520 $this->protect();
1521 }
1522
1526 public function delete() {
1527 # This code desperately needs to be totally rewritten
1528
1529 $title = $this->getTitle();
1530 $context = $this->getContext();
1531 $user = $context->getUser();
1533
1534 # Check permissions
1535 $permissionErrors = $title->getUserPermissionsErrors( 'delete', $user );
1536 if ( count( $permissionErrors ) ) {
1537 throw new PermissionsError( 'delete', $permissionErrors );
1538 }
1539
1540 # Read-only check...
1541 if ( wfReadOnly() ) {
1542 throw new ReadOnlyError;
1543 }
1544
1545 # Better double-check that it hasn't been deleted yet!
1546 $this->mPage->loadPageData(
1547 $request->wasPosted() ? WikiPage::READ_LATEST : WikiPage::READ_NORMAL
1548 );
1549 if ( !$this->mPage->exists() ) {
1550 $deleteLogPage = new LogPage( 'delete' );
1551 $outputPage = $context->getOutput();
1552 $outputPage->setPageTitle( $context->msg( 'cannotdelete-title', $title->getPrefixedText() ) );
1553 $outputPage->wrapWikiMsg( "<div class=\"error mw-error-cannotdelete\">\n$1\n</div>",
1554 [ 'cannotdelete', wfEscapeWikiText( $title->getPrefixedText() ) ]
1555 );
1556 $outputPage->addHTML(
1557 Xml::element( 'h2', null, $deleteLogPage->getName()->text() )
1558 );
1560 $outputPage,
1561 'delete',
1562 $title
1563 );
1564
1565 return;
1566 }
1567
1568 $deleteReasonList = $request->getText( 'wpDeleteReasonList', 'other' );
1569 $deleteReason = $request->getText( 'wpReason' );
1570
1571 if ( $deleteReasonList == 'other' ) {
1572 $reason = $deleteReason;
1573 } elseif ( $deleteReason != '' ) {
1574 // Entry from drop down menu + additional comment
1575 $colonseparator = wfMessage( 'colon-separator' )->inContentLanguage()->text();
1576 $reason = $deleteReasonList . $colonseparator . $deleteReason;
1577 } else {
1578 $reason = $deleteReasonList;
1579 }
1580
1581 if ( $request->wasPosted() && $user->matchEditToken( $request->getVal( 'wpEditToken' ),
1582 [ 'delete', $this->getTitle()->getPrefixedText() ] )
1583 ) {
1584 # Flag to hide all contents of the archived revisions
1585 $suppress = $request->getVal( 'wpSuppress' ) && $user->isAllowed( 'suppressrevision' );
1586
1587 $this->doDelete( $reason, $suppress );
1588
1589 WatchAction::doWatchOrUnwatch( $request->getCheck( 'wpWatch' ), $title, $user );
1590
1591 return;
1592 }
1593
1594 // Generate deletion reason
1595 $hasHistory = false;
1596 if ( !$reason ) {
1597 try {
1598 $reason = $this->generateReason( $hasHistory );
1599 } catch ( Exception $e ) {
1600 # if a page is horribly broken, we still want to be able to
1601 # delete it. So be lenient about errors here.
1602 wfDebug( "Error while building auto delete summary: $e" );
1603 $reason = '';
1604 }
1605 }
1606
1607 // If the page has a history, insert a warning
1608 if ( $hasHistory ) {
1609 $title = $this->getTitle();
1610
1611 // The following can use the real revision count as this is only being shown for users
1612 // that can delete this page.
1613 // This, as a side-effect, also makes sure that the following query isn't being run for
1614 // pages with a larger history, unless the user has the 'bigdelete' right
1615 // (and is about to delete this page).
1616 $dbr = wfGetDB( DB_REPLICA );
1617 $revisions = $edits = (int)$dbr->selectField(
1618 'revision',
1619 'COUNT(rev_page)',
1620 [ 'rev_page' => $title->getArticleID() ],
1621 __METHOD__
1622 );
1623
1624 // @todo FIXME: i18n issue/patchwork message
1625 $context->getOutput()->addHTML(
1626 '<strong class="mw-delete-warning-revisions">' .
1627 $context->msg( 'historywarning' )->numParams( $revisions )->parse() .
1628 $context->msg( 'word-separator' )->escaped() . Linker::linkKnown( $title,
1629 $context->msg( 'history' )->escaped(),
1630 [],
1631 [ 'action' => 'history' ] ) .
1632 '</strong>'
1633 );
1634
1635 if ( $title->isBigDeletion() ) {
1637 $context->getOutput()->wrapWikiMsg( "<div class='error'>\n$1\n</div>\n",
1638 [
1639 'delete-warning-toobig',
1641 ]
1642 );
1643 }
1644 }
1645
1646 $this->confirmDelete( $reason );
1647 }
1648
1654 public function confirmDelete( $reason ) {
1655 wfDebug( "Article::confirmDelete\n" );
1656
1657 $title = $this->getTitle();
1658 $ctx = $this->getContext();
1659 $outputPage = $ctx->getOutput();
1660 $useMediaWikiUIEverywhere = $ctx->getConfig()->get( 'UseMediaWikiUIEverywhere' );
1661 $outputPage->setPageTitle( wfMessage( 'delete-confirm', $title->getPrefixedText() ) );
1662 $outputPage->addBacklinkSubtitle( $title );
1663 $outputPage->setRobotPolicy( 'noindex,nofollow' );
1664 $backlinkCache = $title->getBacklinkCache();
1665 if ( $backlinkCache->hasLinks( 'pagelinks' ) || $backlinkCache->hasLinks( 'templatelinks' ) ) {
1666 $outputPage->wrapWikiMsg( "<div class='mw-warning plainlinks'>\n$1\n</div>\n",
1667 'deleting-backlinks-warning' );
1668 }
1669 $outputPage->addWikiMsg( 'confirmdeletetext' );
1670
1671 Hooks::run( 'ArticleConfirmDelete', [ $this, $outputPage, &$reason ] );
1672
1673 $user = $this->getContext()->getUser();
1674 if ( $user->isAllowed( 'suppressrevision' ) ) {
1675 $suppress = Html::openElement( 'div', [ 'id' => 'wpDeleteSuppressRow' ] ) .
1676 Xml::checkLabel( wfMessage( 'revdelete-suppress' )->text(),
1677 'wpSuppress', 'wpSuppress', false, [ 'tabindex' => '4' ] ) .
1678 Html::closeElement( 'div' );
1679 } else {
1680 $suppress = '';
1681 }
1682 $checkWatch = $user->getBoolOption( 'watchdeletion' ) || $user->isWatched( $title );
1683 $form = Html::openElement( 'form', [ 'method' => 'post',
1684 'action' => $title->getLocalURL( 'action=delete' ), 'id' => 'deleteconfirm' ] ) .
1685 Html::openElement( 'fieldset', [ 'id' => 'mw-delete-table' ] ) .
1686 Html::element( 'legend', null, wfMessage( 'delete-legend' )->text() ) .
1687 Html::openElement( 'div', [ 'id' => 'mw-deleteconfirm-table' ] ) .
1688 Html::openElement( 'div', [ 'id' => 'wpDeleteReasonListRow' ] ) .
1689 Html::label( wfMessage( 'deletecomment' )->text(), 'wpDeleteReasonList' ) .
1690 '&nbsp;' .
1691 Xml::listDropDown(
1692 'wpDeleteReasonList',
1693 wfMessage( 'deletereason-dropdown' )->inContentLanguage()->text(),
1694 wfMessage( 'deletereasonotherlist' )->inContentLanguage()->text(),
1695 '',
1696 'wpReasonDropDown',
1697 1
1698 ) .
1699 Html::closeElement( 'div' ) .
1700 Html::openElement( 'div', [ 'id' => 'wpDeleteReasonRow' ] ) .
1701 Html::label( wfMessage( 'deleteotherreason' )->text(), 'wpReason' ) .
1702 '&nbsp;' .
1703 Html::input( 'wpReason', $reason, 'text', [
1704 'size' => '60',
1705 'maxlength' => '255',
1706 'tabindex' => '2',
1707 'id' => 'wpReason',
1708 'class' => 'mw-ui-input-inline',
1709 'autofocus'
1710 ] ) .
1711 Html::closeElement( 'div' );
1712
1713 # Disallow watching if user is not logged in
1714 if ( $user->isLoggedIn() ) {
1715 $form .=
1716 Xml::checkLabel( wfMessage( 'watchthis' )->text(),
1717 'wpWatch', 'wpWatch', $checkWatch, [ 'tabindex' => '3' ] );
1718 }
1719
1720 $form .=
1721 Html::openElement( 'div' ) .
1722 $suppress .
1723 Xml::submitButton( wfMessage( 'deletepage' )->text(),
1724 [
1725 'name' => 'wpConfirmB',
1726 'id' => 'wpConfirmB',
1727 'tabindex' => '5',
1728 'class' => $useMediaWikiUIEverywhere ? 'mw-ui-button mw-ui-destructive' : '',
1729 ]
1730 ) .
1731 Html::closeElement( 'div' ) .
1732 Html::closeElement( 'div' ) .
1733 Xml::closeElement( 'fieldset' ) .
1734 Html::hidden(
1735 'wpEditToken',
1736 $user->getEditToken( [ 'delete', $title->getPrefixedText() ] )
1737 ) .
1738 Xml::closeElement( 'form' );
1739
1740 if ( $user->isAllowed( 'editinterface' ) ) {
1742 $ctx->msg( 'deletereason-dropdown' )->inContentLanguage()->getTitle(),
1743 wfMessage( 'delete-edit-reasonlist' )->escaped(),
1744 [],
1745 [ 'action' => 'edit' ]
1746 );
1747 $form .= '<p class="mw-delete-editreasons">' . $link . '</p>';
1748 }
1749
1750 $outputPage->addHTML( $form );
1751
1752 $deleteLogPage = new LogPage( 'delete' );
1753 $outputPage->addHTML( Xml::element( 'h2', null, $deleteLogPage->getName()->text() ) );
1754 LogEventsList::showLogExtract( $outputPage, 'delete', $title );
1755 }
1756
1762 public function doDelete( $reason, $suppress = false ) {
1763 $error = '';
1764 $context = $this->getContext();
1765 $outputPage = $context->getOutput();
1766 $user = $context->getUser();
1767 $status = $this->mPage->doDeleteArticleReal( $reason, $suppress, 0, true, $error, $user );
1768
1769 if ( $status->isGood() ) {
1770 $deleted = $this->getTitle()->getPrefixedText();
1771
1772 $outputPage->setPageTitle( wfMessage( 'actioncomplete' ) );
1773 $outputPage->setRobotPolicy( 'noindex,nofollow' );
1774
1775 $loglink = '[[Special:Log/delete|' . wfMessage( 'deletionlog' )->text() . ']]';
1776
1777 $outputPage->addWikiMsg( 'deletedtext', wfEscapeWikiText( $deleted ), $loglink );
1778
1779 Hooks::run( 'ArticleDeleteAfterSuccess', [ $this->getTitle(), $outputPage ] );
1780
1781 $outputPage->returnToMain( false );
1782 } else {
1783 $outputPage->setPageTitle(
1784 wfMessage( 'cannotdelete-title',
1785 $this->getTitle()->getPrefixedText() )
1786 );
1787
1788 if ( $error == '' ) {
1789 $outputPage->addWikiText(
1790 "<div class=\"error mw-error-cannotdelete\">\n" . $status->getWikiText() . "\n</div>"
1791 );
1792 $deleteLogPage = new LogPage( 'delete' );
1793 $outputPage->addHTML( Xml::element( 'h2', null, $deleteLogPage->getName()->text() ) );
1794
1796 $outputPage,
1797 'delete',
1798 $this->getTitle()
1799 );
1800 } else {
1801 $outputPage->addHTML( $error );
1802 }
1803 }
1804 }
1805
1806 /* Caching functions */
1807
1815 protected function tryFileCache() {
1816 static $called = false;
1817
1818 if ( $called ) {
1819 wfDebug( "Article::tryFileCache(): called twice!?\n" );
1820 return false;
1821 }
1822
1823 $called = true;
1824 if ( $this->isFileCacheable() ) {
1825 $cache = new HTMLFileCache( $this->getTitle(), 'view' );
1826 if ( $cache->isCacheGood( $this->mPage->getTouched() ) ) {
1827 wfDebug( "Article::tryFileCache(): about to load file\n" );
1828 $cache->loadFromFileCache( $this->getContext() );
1829 return true;
1830 } else {
1831 wfDebug( "Article::tryFileCache(): starting buffer\n" );
1832 ob_start( [ &$cache, 'saveToFileCache' ] );
1833 }
1834 } else {
1835 wfDebug( "Article::tryFileCache(): not cacheable\n" );
1836 }
1837
1838 return false;
1839 }
1840
1846 public function isFileCacheable( $mode = HTMLFileCache::MODE_NORMAL ) {
1847 $cacheable = false;
1848
1849 if ( HTMLFileCache::useFileCache( $this->getContext(), $mode ) ) {
1850 $cacheable = $this->mPage->getId()
1851 && !$this->mRedirectedFrom && !$this->getTitle()->isRedirect();
1852 // Extension may have reason to disable file caching on some pages.
1853 if ( $cacheable ) {
1854 // Avoid PHP 7.1 warning of passing $this by reference
1855 $articlePage = $this;
1856 $cacheable = Hooks::run( 'IsFileCacheable', [ &$articlePage ] );
1857 }
1858 }
1859
1860 return $cacheable;
1861 }
1862
1876 public function getParserOutput( $oldid = null, User $user = null ) {
1877 // XXX: bypasses mParserOptions and thus setParserOptions()
1878
1879 if ( $user === null ) {
1880 $parserOptions = $this->getParserOptions();
1881 } else {
1882 $parserOptions = $this->mPage->makeParserOptions( $user );
1883 }
1884
1885 return $this->mPage->getParserOutput( $parserOptions, $oldid );
1886 }
1887
1895 if ( $this->mParserOptions ) {
1896 throw new MWException( "can't change parser options after they have already been set" );
1897 }
1898
1899 // clone, so if $options is modified later, it doesn't confuse the parser cache.
1900 $this->mParserOptions = clone $options;
1901 }
1902
1907 public function getParserOptions() {
1908 if ( !$this->mParserOptions ) {
1909 $this->mParserOptions = $this->mPage->makeParserOptions( $this->getContext() );
1910 }
1911 // Clone to allow modifications of the return value without affecting cache
1912 return clone $this->mParserOptions;
1913 }
1914
1921 public function setContext( $context ) {
1922 $this->mContext = $context;
1923 }
1924
1931 public function getContext() {
1932 if ( $this->mContext instanceof IContextSource ) {
1933 return $this->mContext;
1934 } else {
1935 wfDebug( __METHOD__ . " called and \$mContext is null. " .
1936 "Return RequestContext::getMain(); for sanity\n" );
1937 return RequestContext::getMain();
1938 }
1939 }
1940
1948 public function __get( $fname ) {
1949 if ( property_exists( $this->mPage, $fname ) ) {
1950 # wfWarn( "Access to raw $fname field " . __CLASS__ );
1951 return $this->mPage->$fname;
1952 }
1953 trigger_error( 'Inaccessible property via __get(): ' . $fname, E_USER_NOTICE );
1954 }
1955
1963 public function __set( $fname, $fvalue ) {
1964 if ( property_exists( $this->mPage, $fname ) ) {
1965 # wfWarn( "Access to raw $fname field of " . __CLASS__ );
1966 $this->mPage->$fname = $fvalue;
1967 // Note: extensions may want to toss on new fields
1968 } elseif ( !in_array( $fname, [ 'mContext', 'mPage' ] ) ) {
1969 $this->mPage->$fname = $fvalue;
1970 } else {
1971 trigger_error( 'Inaccessible property via __set(): ' . $fname, E_USER_NOTICE );
1972 }
1973 }
1974
1979 public function checkFlags( $flags ) {
1980 return $this->mPage->checkFlags( $flags );
1981 }
1982
1987 public function checkTouched() {
1988 return $this->mPage->checkTouched();
1989 }
1990
1995 public function clearPreparedEdit() {
1996 $this->mPage->clearPreparedEdit();
1997 }
1998
2003 public function doDeleteArticleReal(
2004 $reason, $suppress = false, $u1 = null, $u2 = null, &$error = '', User $user = null,
2005 $tags = []
2006 ) {
2007 return $this->mPage->doDeleteArticleReal(
2008 $reason, $suppress, $u1, $u2, $error, $user, $tags
2009 );
2010 }
2011
2016 public function doDeleteUpdates( $id, Content $content = null ) {
2017 return $this->mPage->doDeleteUpdates( $id, $content );
2018 }
2019
2025 public function doEditContent( Content $content, $summary, $flags = 0, $baseRevId = false,
2026 User $user = null, $serialFormat = null
2027 ) {
2028 wfDeprecated( __METHOD__, '1.29' );
2029 return $this->mPage->doEditContent( $content, $summary, $flags, $baseRevId,
2030 $user, $serialFormat
2031 );
2032 }
2033
2038 public function doEditUpdates( Revision $revision, User $user, array $options = [] ) {
2039 return $this->mPage->doEditUpdates( $revision, $user, $options );
2040 }
2041
2048 public function doPurge() {
2049 return $this->mPage->doPurge();
2050 }
2051
2057 public function getLastPurgeTimestamp() {
2058 wfDeprecated( __METHOD__, '1.29' );
2059 return $this->mPage->getLastPurgeTimestamp();
2060 }
2061
2066 public function doViewUpdates( User $user, $oldid = 0 ) {
2067 $this->mPage->doViewUpdates( $user, $oldid );
2068 }
2069
2074 public function exists() {
2075 return $this->mPage->exists();
2076 }
2077
2082 public function followRedirect() {
2083 return $this->mPage->followRedirect();
2084 }
2085
2090 public function getActionOverrides() {
2091 return $this->mPage->getActionOverrides();
2092 }
2093
2098 public function getAutoDeleteReason( &$hasHistory ) {
2099 return $this->mPage->getAutoDeleteReason( $hasHistory );
2100 }
2101
2106 public function getCategories() {
2107 return $this->mPage->getCategories();
2108 }
2109
2114 public function getComment( $audience = Revision::FOR_PUBLIC, User $user = null ) {
2115 return $this->mPage->getComment( $audience, $user );
2116 }
2117
2122 public function getContentHandler() {
2123 return $this->mPage->getContentHandler();
2124 }
2125
2130 public function getContentModel() {
2131 return $this->mPage->getContentModel();
2132 }
2133
2138 public function getContributors() {
2139 return $this->mPage->getContributors();
2140 }
2141
2146 public function getCreator( $audience = Revision::FOR_PUBLIC, User $user = null ) {
2147 return $this->mPage->getCreator( $audience, $user );
2148 }
2149
2154 public function getDeletionUpdates( Content $content = null ) {
2155 return $this->mPage->getDeletionUpdates( $content );
2156 }
2157
2162 public function getHiddenCategories() {
2163 return $this->mPage->getHiddenCategories();
2164 }
2165
2170 public function getId() {
2171 return $this->mPage->getId();
2172 }
2173
2178 public function getLatest() {
2179 return $this->mPage->getLatest();
2180 }
2181
2186 public function getLinksTimestamp() {
2187 return $this->mPage->getLinksTimestamp();
2188 }
2189
2194 public function getMinorEdit() {
2195 return $this->mPage->getMinorEdit();
2196 }
2197
2202 public function getOldestRevision() {
2203 return $this->mPage->getOldestRevision();
2204 }
2205
2210 public function getRedirectTarget() {
2211 return $this->mPage->getRedirectTarget();
2212 }
2213
2218 public function getRedirectURL( $rt ) {
2219 return $this->mPage->getRedirectURL( $rt );
2220 }
2221
2226 public function getRevision() {
2227 return $this->mPage->getRevision();
2228 }
2229
2234 public function getTimestamp() {
2235 return $this->mPage->getTimestamp();
2236 }
2237
2242 public function getTouched() {
2243 return $this->mPage->getTouched();
2244 }
2245
2250 public function getUndoContent( Revision $undo, Revision $undoafter = null ) {
2251 return $this->mPage->getUndoContent( $undo, $undoafter );
2252 }
2253
2258 public function getUser( $audience = Revision::FOR_PUBLIC, User $user = null ) {
2259 return $this->mPage->getUser( $audience, $user );
2260 }
2261
2266 public function getUserText( $audience = Revision::FOR_PUBLIC, User $user = null ) {
2267 return $this->mPage->getUserText( $audience, $user );
2268 }
2269
2274 public function hasViewableContent() {
2275 return $this->mPage->hasViewableContent();
2276 }
2277
2282 public function insertOn( $dbw, $pageId = null ) {
2283 return $this->mPage->insertOn( $dbw, $pageId );
2284 }
2285
2290 public function insertProtectNullRevision( $revCommentMsg, array $limit,
2291 array $expiry, $cascade, $reason, $user = null
2292 ) {
2293 return $this->mPage->insertProtectNullRevision( $revCommentMsg, $limit,
2294 $expiry, $cascade, $reason, $user
2295 );
2296 }
2297
2302 public function insertRedirect() {
2303 return $this->mPage->insertRedirect();
2304 }
2305
2310 public function insertRedirectEntry( Title $rt, $oldLatest = null ) {
2311 return $this->mPage->insertRedirectEntry( $rt, $oldLatest );
2312 }
2313
2318 public function isCountable( $editInfo = false ) {
2319 return $this->mPage->isCountable( $editInfo );
2320 }
2321
2326 public function isRedirect() {
2327 return $this->mPage->isRedirect();
2328 }
2329
2334 public function loadFromRow( $data, $from ) {
2335 return $this->mPage->loadFromRow( $data, $from );
2336 }
2337
2342 public function loadPageData( $from = 'fromdb' ) {
2343 $this->mPage->loadPageData( $from );
2344 }
2345
2350 public function lockAndGetLatest() {
2351 return $this->mPage->lockAndGetLatest();
2352 }
2353
2358 public function makeParserOptions( $context ) {
2359 return $this->mPage->makeParserOptions( $context );
2360 }
2361
2366 public function pageDataFromId( $dbr, $id, $options = [] ) {
2367 return $this->mPage->pageDataFromId( $dbr, $id, $options );
2368 }
2369
2374 public function pageDataFromTitle( $dbr, $title, $options = [] ) {
2375 return $this->mPage->pageDataFromTitle( $dbr, $title, $options );
2376 }
2377
2382 public function prepareContentForEdit(
2383 Content $content, $revision = null, User $user = null,
2384 $serialFormat = null, $useCache = true
2385 ) {
2386 return $this->mPage->prepareContentForEdit(
2387 $content, $revision, $user,
2388 $serialFormat, $useCache
2389 );
2390 }
2391
2396 public function protectDescription( array $limit, array $expiry ) {
2397 return $this->mPage->protectDescription( $limit, $expiry );
2398 }
2399
2404 public function protectDescriptionLog( array $limit, array $expiry ) {
2405 return $this->mPage->protectDescriptionLog( $limit, $expiry );
2406 }
2407
2412 public function replaceSectionAtRev( $sectionId, Content $sectionContent,
2413 $sectionTitle = '', $baseRevId = null
2414 ) {
2415 return $this->mPage->replaceSectionAtRev( $sectionId, $sectionContent,
2416 $sectionTitle, $baseRevId
2417 );
2418 }
2419
2424 public function replaceSectionContent(
2425 $sectionId, Content $sectionContent, $sectionTitle = '', $edittime = null
2426 ) {
2427 return $this->mPage->replaceSectionContent(
2428 $sectionId, $sectionContent, $sectionTitle, $edittime
2429 );
2430 }
2431
2436 public function setTimestamp( $ts ) {
2437 return $this->mPage->setTimestamp( $ts );
2438 }
2439
2444 public function shouldCheckParserCache( ParserOptions $parserOptions, $oldId ) {
2445 return $this->mPage->shouldCheckParserCache( $parserOptions, $oldId );
2446 }
2447
2452 public function supportsSections() {
2453 return $this->mPage->supportsSections();
2454 }
2455
2461 return $this->mPage->triggerOpportunisticLinksUpdate( $parserOutput );
2462 }
2463
2468 public function updateCategoryCounts( array $added, array $deleted, $id = 0 ) {
2469 return $this->mPage->updateCategoryCounts( $added, $deleted, $id );
2470 }
2471
2476 public function updateIfNewerOn( $dbw, $revision ) {
2477 return $this->mPage->updateIfNewerOn( $dbw, $revision );
2478 }
2479
2484 public function updateRedirectOn( $dbw, $redirectTitle, $lastRevIsRedirect = null ) {
2485 return $this->mPage->updateRedirectOn( $dbw, $redirectTitle, $lastRevIsRedirect = null );
2486 }
2487
2492 public function updateRevisionOn( $dbw, $revision, $lastRevision = null,
2493 $lastRevIsRedirect = null
2494 ) {
2495 return $this->mPage->updateRevisionOn( $dbw, $revision, $lastRevision,
2496 $lastRevIsRedirect
2497 );
2498 }
2499
2508 public function doUpdateRestrictions( array $limit, array $expiry, &$cascade,
2509 $reason, User $user
2510 ) {
2511 return $this->mPage->doUpdateRestrictions( $limit, $expiry, $cascade, $reason, $user );
2512 }
2513
2521 public function updateRestrictions( $limit = [], $reason = '',
2522 &$cascade = 0, $expiry = []
2523 ) {
2524 return $this->mPage->doUpdateRestrictions(
2525 $limit,
2526 $expiry,
2527 $cascade,
2528 $reason,
2529 $this->getContext()->getUser()
2530 );
2531 }
2532
2541 public function doDeleteArticle(
2542 $reason, $suppress = false, $u1 = null, $u2 = null, &$error = ''
2543 ) {
2544 return $this->mPage->doDeleteArticle( $reason, $suppress, $u1, $u2, $error );
2545 }
2546
2556 public function doRollback( $fromP, $summary, $token, $bot, &$resultDetails, User $user = null ) {
2557 $user = is_null( $user ) ? $this->getContext()->getUser() : $user;
2558 return $this->mPage->doRollback( $fromP, $summary, $token, $bot, $resultDetails, $user );
2559 }
2560
2569 public function commitRollback( $fromP, $summary, $bot, &$resultDetails, User $guser = null ) {
2570 $guser = is_null( $guser ) ? $this->getContext()->getUser() : $guser;
2571 return $this->mPage->commitRollback( $fromP, $summary, $bot, $resultDetails, $guser );
2572 }
2573
2578 public function generateReason( &$hasHistory ) {
2579 $title = $this->mPage->getTitle();
2581 return $handler->getAutoDeleteReason( $title, $hasHistory );
2582 }
2583
2589 public static function selectFields() {
2590 wfDeprecated( __METHOD__, '1.24' );
2591 return WikiPage::selectFields();
2592 }
2593
2599 public static function onArticleCreate( $title ) {
2600 wfDeprecated( __METHOD__, '1.24' );
2602 }
2603
2609 public static function onArticleDelete( $title ) {
2610 wfDeprecated( __METHOD__, '1.24' );
2612 }
2613
2619 public static function onArticleEdit( $title ) {
2620 wfDeprecated( __METHOD__, '1.24' );
2622 }
2623
2624 // ******
2625}
Apache License January AND DISTRIBUTION Definitions License shall mean the terms and conditions for use
$wgArticleRobotPolicies
Robot policies per article.
$wgDefaultRobotPolicy
Default robot policy.
$wgSend404Code
Some web hosts attempt to rewrite all responses with a 404 (not found) status code,...
$wgRedirectSources
If local interwikis are set up which allow redirects, set this regexp to restrict URLs which will be ...
$wgUseFilePatrol
Use file patrolling to check new files on Special:Newfiles.
$wgUseRCPatrol
Use RC Patrolling to check for vandalism (from recent changes and watchlists) New pages and new files...
$wgEnableWriteAPI
Allow the API to be used to perform write operations (page edits, rollback, etc.) when an authorised ...
$wgNamespaceRobotPolicies
Robot policies per namespaces.
$wgUseNPPatrol
Use new page patrolling to check new pages on Special:Newpages.
$wgDeleteRevisionsLimit
Optional to restrict deletion of pages with higher revision counts to users with the 'bigdelete' perm...
$wgDebugToolbar
Display the new debugging toolbar.
$wgEnableAPI
Enable the MediaWiki API for convenient access to machine-readable data via api.php.
$wgUseFileCache
This will cache static pages for non-logged-in users to reduce database traffic on public sites.
wfDebug( $text, $dest='all', array $context=[])
Sends a line to the debug log if enabled or, optionally, to a comment in output.
wfReadOnly()
Check whether the wiki is in read-only mode.
wfGetDB( $db, $groups=[], $wiki=false)
Get a Database object.
wfMemcKey()
Make a cache key for the local wiki.
wfEscapeWikiText( $text)
Escapes the given text so that it may be output using addWikiText() without any linking,...
wfDeprecated( $function, $version=false, $component=false, $callerOffset=2)
Throws a warning that $function is deprecated.
if(!defined( 'MEDIAWIKI')) $fname
This file is not a valid entry point, perform no further processing unless MEDIAWIKI is defined.
Definition Setup.php:36
Class for viewing MediaWiki article and history.
Definition Article.php:35
shouldCheckParserCache(ParserOptions $parserOptions, $oldId)
Call to WikiPage function for backwards compatibility.
Definition Article.php:2444
getRevisionFetched()
Get the fetched Revision object depending on request parameters or null on failure.
Definition Article.php:406
ParserOutput $mParserOutput
Definition Article.php:76
Title $mRedirectedFrom
Title from which we were redirected here.
Definition Article.php:64
updateRedirectOn( $dbw, $redirectTitle, $lastRevIsRedirect=null)
Call to WikiPage function for backwards compatibility.
Definition Article.php:2484
generateReason(&$hasHistory)
Definition Article.php:2578
checkFlags( $flags)
Call to WikiPage function for backwards compatibility.
Definition Article.php:1979
doDeleteArticleReal( $reason, $suppress=false, $u1=null, $u2=null, &$error='', User $user=null, $tags=[])
Call to WikiPage function for backwards compatibility.
Definition Article.php:2003
checkTouched()
Call to WikiPage function for backwards compatibility.
Definition Article.php:1987
doDelete( $reason, $suppress=false)
Perform a deletion and output success or failure messages.
Definition Article.php:1762
getHiddenCategories()
Call to WikiPage function for backwards compatibility.
Definition Article.php:2162
static newFromWikiPage(WikiPage $page, IContextSource $context)
Create an Article object of the appropriate class for the given page.
Definition Article.php:145
doViewUpdates(User $user, $oldid=0)
Call to WikiPage function for backwards compatibility.
Definition Article.php:2066
getContext()
Gets the context this Article is executed in.
Definition Article.php:1931
getCategories()
Call to WikiPage function for backwards compatibility.
Definition Article.php:2106
commitRollback( $fromP, $summary, $bot, &$resultDetails, User $guser=null)
Definition Article.php:2569
getOldIDFromRequest()
Sets $this->mRedirectUrl to a correct URL if the query parameters are incorrect.
Definition Article.php:256
doEditContent(Content $content, $summary, $flags=0, $baseRevId=false, User $user=null, $serialFormat=null)
Call to WikiPage function for backwards compatibility.
Definition Article.php:2025
getParserOutput( $oldid=null, User $user=null)
#-
Definition Article.php:1876
insertProtectNullRevision( $revCommentMsg, array $limit, array $expiry, $cascade, $reason, $user=null)
Call to WikiPage function for backwards compatibility.
Definition Article.php:2290
doPurge()
Call to WikiPage function for backwards compatibility.
Definition Article.php:2048
getRedirectedFrom()
Get the page this view was redirected from.
Definition Article.php:156
getUserText( $audience=Revision::FOR_PUBLIC, User $user=null)
Call to WikiPage function for backwards compatibility.
Definition Article.php:2266
insertOn( $dbw, $pageId=null)
Call to WikiPage function for backwards compatibility.
Definition Article.php:2282
updateRevisionOn( $dbw, $revision, $lastRevision=null, $lastRevIsRedirect=null)
Call to WikiPage function for backwards compatibility.
Definition Article.php:2492
IContextSource $mContext
The context this Article is executed in.
Definition Article.php:37
fetchContentObject()
Get text content object Does NOT follow redirects.
Definition Article.php:314
supportsSections()
Call to WikiPage function for backwards compatibility.
Definition Article.php:2452
string $mContent
Text of the revision we are working on.
Definition Article.php:49
pageDataFromTitle( $dbr, $title, $options=[])
Call to WikiPage function for backwards compatibility.
Definition Article.php:2374
getContentHandler()
Call to WikiPage function for backwards compatibility.
Definition Article.php:2122
updateCategoryCounts(array $added, array $deleted, $id=0)
Call to WikiPage function for backwards compatibility.
Definition Article.php:2468
view()
This is the default action of the index.php entry point: just view the page of the given title.
Definition Article.php:429
loadPageData( $from='fromdb')
Call to WikiPage function for backwards compatibility.
Definition Article.php:2342
getRobotPolicy( $action, $pOutput=null)
Get the robot policy to be used for the current view.
Definition Article.php:725
doUpdateRestrictions(array $limit, array $expiry, &$cascade, $reason, User $user)
Definition Article.php:2508
protectDescriptionLog(array $limit, array $expiry)
Call to WikiPage function for backwards compatibility.
Definition Article.php:2404
clearPreparedEdit()
Call to WikiPage function for backwards compatibility.
Definition Article.php:1995
__construct(Title $title, $oldId=null)
Constructor and clear the article.
Definition Article.php:83
static purgePatrolFooterCache( $articleID)
Purge the cache used to check if it is worth showing the patrol footer For example,...
Definition Article.php:1112
followRedirect()
Call to WikiPage function for backwards compatibility.
Definition Article.php:2082
prepareContentForEdit(Content $content, $revision=null, User $user=null, $serialFormat=null, $useCache=true)
Call to WikiPage function for backwards compatibility.
Definition Article.php:2382
static selectFields()
Definition Article.php:2589
replaceSectionAtRev( $sectionId, Content $sectionContent, $sectionTitle='', $baseRevId=null)
Call to WikiPage function for backwards compatibility.
Definition Article.php:2412
getAutoDeleteReason(&$hasHistory)
Call to WikiPage function for backwards compatibility.
Definition Article.php:2098
getLinksTimestamp()
Call to WikiPage function for backwards compatibility.
Definition Article.php:2186
getOldID()
Definition Article.php:243
protectDescription(array $limit, array $expiry)
Call to WikiPage function for backwards compatibility.
Definition Article.php:2396
getOldestRevision()
Call to WikiPage function for backwards compatibility.
Definition Article.php:2202
static onArticleEdit( $title)
Definition Article.php:2619
setTimestamp( $ts)
Call to WikiPage function for backwards compatibility.
Definition Article.php:2436
getTitle()
Get the title object of the article.
Definition Article.php:174
getActionOverrides()
Call to WikiPage function for backwards compatibility.
Definition Article.php:2090
doEditUpdates(Revision $revision, User $user, array $options=[])
Call to WikiPage function for backwards compatibility.
Definition Article.php:2038
getLastPurgeTimestamp()
Call to WikiPage function for backwards compatibility.
Definition Article.php:2057
adjustDisplayTitle(ParserOutput $pOutput)
Adjust title for pages with displaytitle, -{T|}- or language conversion.
Definition Article.php:663
updateIfNewerOn( $dbw, $revision)
Call to WikiPage function for backwards compatibility.
Definition Article.php:2476
getLatest()
Call to WikiPage function for backwards compatibility.
Definition Article.php:2178
pageDataFromId( $dbr, $id, $options=[])
Call to WikiPage function for backwards compatibility.
Definition Article.php:2366
insertRedirect()
Call to WikiPage function for backwards compatibility.
Definition Article.php:2302
doDeleteUpdates( $id, Content $content=null)
Call to WikiPage function for backwards compatibility.
Definition Article.php:2016
getContributors()
Call to WikiPage function for backwards compatibility.
Definition Article.php:2138
showDeletedRevisionHeader()
If the revision requested for view is deleted, check permissions.
Definition Article.php:1246
isCountable( $editInfo=false)
Call to WikiPage function for backwards compatibility.
Definition Article.php:2318
getParserOptions()
Get parser options suitable for rendering the primary article wikitext.
Definition Article.php:1907
getCreator( $audience=Revision::FOR_PUBLIC, User $user=null)
Call to WikiPage function for backwards compatibility.
Definition Article.php:2146
clear()
Clear the object.
Definition Article.php:191
getComment( $audience=Revision::FOR_PUBLIC, User $user=null)
Call to WikiPage function for backwards compatibility.
Definition Article.php:2114
Content $mContentObject
Content of the revision we are working on.
Definition Article.php:55
getContentModel()
Call to WikiPage function for backwards compatibility.
Definition Article.php:2130
static getRedirectHeaderHtml(Language $lang, $target, $forceKnown=false)
Return the HTML for the top of a redirect page.
Definition Article.php:1449
protect()
action=protect handler
Definition Article.php:1511
lockAndGetLatest()
Call to WikiPage function for backwards compatibility.
Definition Article.php:2350
isCurrent()
Returns true if the currently-referenced revision is the current edit to this page (and it exists).
Definition Article.php:390
updateRestrictions( $limit=[], $reason='', &$cascade=0, $expiry=[])
Definition Article.php:2521
showMissingArticle()
Show the error text for a missing article.
Definition Article.php:1121
getUndoContent(Revision $undo, Revision $undoafter=null)
Call to WikiPage function for backwards compatibility.
Definition Article.php:2250
__set( $fname, $fvalue)
Use PHP's magic __set handler to handle setting of raw WikiPage fields for backwards compatibility.
Definition Article.php:1963
doDeleteArticle( $reason, $suppress=false, $u1=null, $u2=null, &$error='')
Definition Article.php:2541
getId()
Call to WikiPage function for backwards compatibility.
Definition Article.php:2170
unprotect()
action=unprotect handler (alias)
Definition Article.php:1519
int $mRevIdFetched
Revision ID of revision we are working on.
Definition Article.php:70
isRedirect()
Call to WikiPage function for backwards compatibility.
Definition Article.php:2326
static onArticleCreate( $title)
Definition Article.php:2599
newPage(Title $title)
Definition Article.php:92
confirmDelete( $reason)
Output deletion confirmation dialog.
Definition Article.php:1654
getPage()
Get the WikiPage object of this instance.
Definition Article.php:184
addHelpLink( $to, $overrideBaseUrl=false)
Adds help link with an icon via page indicators.
Definition Article.php:1484
getTouched()
Call to WikiPage function for backwards compatibility.
Definition Article.php:2242
getRevision()
Call to WikiPage function for backwards compatibility.
Definition Article.php:2226
string bool $mRedirectUrl
URL to redirect to or false if none.
Definition Article.php:67
getTimestamp()
Call to WikiPage function for backwards compatibility.
Definition Article.php:2234
static newFromID( $id)
Constructor from a page id.
Definition Article.php:101
getRedirectTarget()
Call to WikiPage function for backwards compatibility.
Definition Article.php:2210
getUser( $audience=Revision::FOR_PUBLIC, User $user=null)
Call to WikiPage function for backwards compatibility.
Definition Article.php:2258
int null $mOldId
The oldid of the article that is to be shown, 0 for the current revision.
Definition Article.php:61
static formatRobotPolicy( $policy)
Converts a String robot policy into an associative array, to allow merging of several policies using ...
Definition Article.php:805
Revision $mRevision
Revision we are working on.
Definition Article.php:73
viewRedirect( $target, $appendSubtitle=true, $forceKnown=false)
Return the HTML for the top of a redirect page.
Definition Article.php:1427
insertRedirectEntry(Title $rt, $oldLatest=null)
Call to WikiPage function for backwards compatibility.
Definition Article.php:2310
triggerOpportunisticLinksUpdate(ParserOutput $parserOutput)
Call to WikiPage function for backwards compatibility.
Definition Article.php:2460
static onArticleDelete( $title)
Definition Article.php:2609
makeParserOptions( $context)
Call to WikiPage function for backwards compatibility.
Definition Article.php:2358
showPatrolFooter()
If patrol is possible, output a patrol UI box.
Definition Article.php:948
setOldSubtitle( $oldid=0)
Generate the navigation links when browsing through an article revisions It shows the information as:...
Definition Article.php:1289
ParserOptions $mParserOptions
ParserOptions object for $wgUser articles.
Definition Article.php:43
showViewFooter()
Show the footer section of an ordinary page view.
Definition Article.php:925
WikiPage $mPage
The WikiPage object of this instance.
Definition Article.php:40
loadFromRow( $data, $from)
Call to WikiPage function for backwards compatibility.
Definition Article.php:2334
setRedirectedFrom(Title $from)
Tell the page view functions that this view was redirected from another page on the wiki.
Definition Article.php:165
isFileCacheable( $mode=HTMLFileCache::MODE_NORMAL)
Check if the page can be cached.
Definition Article.php:1846
tryFileCache()
checkLastModified returns true if it has taken care of all output to the client that is necessary for...
Definition Article.php:1815
getRevIdFetched()
Use this to fetch the rev ID used on page views.
Definition Article.php:417
replaceSectionContent( $sectionId, Content $sectionContent, $sectionTitle='', $edittime=null)
Call to WikiPage function for backwards compatibility.
Definition Article.php:2424
showNamespaceHeader()
Show a header specific to the namespace currently being viewed, like [[MediaWiki:Talkpagetext]].
Definition Article.php:911
__get( $fname)
Use PHP's magic __get handler to handle accessing of raw WikiPage fields for backwards compatibility.
Definition Article.php:1948
static newFromTitle( $title, IContextSource $context)
Create an Article object of the appropriate class for the given page.
Definition Article.php:113
hasViewableContent()
Call to WikiPage function for backwards compatibility.
Definition Article.php:2274
getContentObject()
Returns a Content object representing the pages effective display content, not necessarily the revisi...
Definition Article.php:216
showDiffPage()
Show a diff page according to current request variables.
Definition Article.php:675
getMinorEdit()
Call to WikiPage function for backwards compatibility.
Definition Article.php:2194
setParserOptions(ParserOptions $options)
Override the ParserOptions used to render the primary article wikitext.
Definition Article.php:1894
render()
Handle action=render.
Definition Article.php:1501
showRedirectedFromHeader()
If this request is a redirect view, send "redirected from" subtitle to the output.
Definition Article.php:834
exists()
Call to WikiPage function for backwards compatibility.
Definition Article.php:2074
setContext( $context)
Sets the context this Article is executed in.
Definition Article.php:1921
getRedirectURL( $rt)
Call to WikiPage function for backwards compatibility.
Definition Article.php:2218
bool $mContentLoaded
Is the content ($mContent) already loaded?
Definition Article.php:58
getDeletionUpdates(Content $content=null)
Call to WikiPage function for backwards compatibility.
Definition Article.php:2154
doRollback( $fromP, $summary, $token, $bot, &$resultDetails, User $user=null)
Definition Article.php:2556
const TYPE_AUTO
Definition Block.php:86
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:1113
Special handling for category description pages, showing pages, subcategories and file that belong to...
static makeContent( $text, Title $title=null, $modelId=null, $format=null)
Convenience function for creating a Content object from a given textual representation.
static getForTitle(Title $title)
Returns the appropriate ContentHandler singleton for the given title.
getUser()
Get the User object.
getRequest()
Get the WebRequest object.
msg()
Get a Message object with context set Parameters are the same as wfMessage()
getOutput()
Get the OutputPage object.
getLanguage()
Get the Language object.
Page view caching in the file system.
static useFileCache(IContextSource $context, $mode=self::MODE_NORMAL)
Check if pages can be cached for this request/user.
Class for viewing MediaWiki file description pages.
Definition ImagePage.php:30
Internationalisation code.
Definition Language.php:35
static link( $target, $html=null, $customAttribs=[], $query=[], $options=[])
This function returns an HTML link to the given target.
Definition Linker.php:107
static linkKnown( $target, $html=null, $customAttribs=[], $query=[], $options=[ 'known'])
Identical to link(), except $options defaults to 'known'.
Definition Linker.php:159
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:1464
static revUserTools( $rev, $isPublic=false)
Generate a user tool link cluster if the current user is allowed to view it.
Definition Linker.php:1055
static makeExternalLink( $url, $text, $escape=true, $linktype='', $attribs=[], $title=null)
Make an external link.
Definition Linker.php:838
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:2017
static showLogExtract(&$out, $types=[], $page='', $user='', $param=[])
Show log extract.
Class to simplify the use of log pages.
Definition LogPage.php:31
MediaWiki exception.
MediaWikiServices is the service locator for the application scope of MediaWiki.
Wrapper allowing us to handle a system message as a Content object.
static singleton()
Get an instance of this object.
Set options of the Parser.
Show an error when a user tries to do something they do not have the necessary permissions for.
Handles the page protection UI and backend.
Show an error when the wiki is locked/read-only and the user tries to do something that requires writ...
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...
static newFromConds( $conds, $fname=__METHOD__, $dbType=DB_REPLICA)
Find the first recent change matching some specific conditions.
static getMain()
Static methods.
const DELETED_TEXT
Definition Revision.php:90
const DELETED_RESTRICTED
Definition Revision.php:93
const FOR_PUBLIC
Definition Revision.php:98
const FOR_THIS_USER
Definition Revision.php:99
static newFromId( $id, $flags=0)
Load a page revision from a given revision ID number.
Definition Revision.php:116
static makeUrl( $name, $urlaction='')
Definition Skin.php:1119
Represents a title within MediaWiki.
Definition Title.php:39
The User object encapsulates all of the user-specific settings (user_id, name, rights,...
Definition User.php:50
static doWatchOrUnwatch( $watch, Title $title, User $user)
Watch or unwatch a page.
Class representing a MediaWiki article and history.
Definition WikiPage.php:36
static onArticleEdit(Title $title, Revision $revision=null)
Purge caches on page update etc.
static onArticleDelete(Title $title)
Clears caches when article is deleted.
static selectFields()
Return the list of revision fields that should be selected to create a new page.
Definition WikiPage.php:286
static onArticleCreate(Title $title)
The onArticle*() functions are supposed to be a kind of hooks which should be called whenever any of ...
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
when a variable name is used in a it is silently declared as a new local masking the global
Definition design.txt:95
design txt This is a brief overview of the new design More thorough and up to date information is available on the documentation wiki at etc Handles the details of getting and saving to the user table of the and dealing with sessions and cookies OutputPage Encapsulates the entire HTML page that will be sent in response to any server request It is used by calling its functions to add text
Definition design.txt:18
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
const NS_USER
Definition Defines.php:64
const NS_FILE
Definition Defines.php:68
const NS_MEDIAWIKI
Definition Defines.php:70
const RC_LOG
Definition Defines.php:142
const NS_MEDIA
Definition Defines.php:50
const NS_USER_TALK
Definition Defines.php:65
const NS_CATEGORY
Definition Defines.php:76
the array() calling protocol came about after MediaWiki 1.4rc1.
null for the local 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:1614
this hook is for auditing only RecentChangesLinked and Watchlist RecentChangesLinked and Watchlist Do not use this to implement individual filters if they are compatible with the ChangesListFilter and ChangesListFilterGroup structure use sub classes of those in conjunction with the ChangesListSpecialPageStructuredFilters hook This hook can be used to implement filters that do not implement that or custom behavior that is not an individual filter e g Watchlist and Watchlist you will want to construct new ChangesListBooleanFilter or ChangesListStringOptionsFilter objects When constructing you specify which group they belong to You can reuse existing or create your you must register them with $special registerFilterGroup removed from all revisions and log entries to which it was applied This gives extensions a chance to take it off their books as the deletion has already been partly carried out by this point or something similar the user will be unable to create the tag set and then return false from the hook function Ensure you consume the ChangeTagAfterDelete hook to carry out custom deletion actions as context $parserOutput
Definition hooks.txt:1096
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 local account $user
Definition hooks.txt:249
error also a ContextSource you ll probably need to make sure the header is varied on and they can depend only on the ResourceLoaderContext $context
Definition hooks.txt:2728
do that in ParserLimitReportFormat instead use this to modify the parameters of the image and a DIV can begin in one section and end in another Make sure your code can handle that case gracefully See the EditSectionClearerLink extension for an example zero but section is usually empty its values are the globals values before the output is cached $page
Definition hooks.txt:2578
this hook is for auditing only RecentChangesLinked and Watchlist RecentChangesLinked and Watchlist Do not use this to implement individual filters if they are compatible with the ChangesListFilter and ChangesListFilterGroup structure use sub classes of those in conjunction with the ChangesListSpecialPageStructuredFilters hook This hook can be used to implement filters that do not implement that or custom behavior that is not an individual filter e g Watchlist and Watchlist you will want to construct new ChangesListBooleanFilter or ChangesListStringOptionsFilter objects When constructing you specify which group they belong to You can reuse existing or create your you must register them with $special registerFilterGroup removed from all revisions and log entries to which it was applied This gives extensions a chance to take it off their books as the deletion has already been partly carried out by this point or something similar the user will be unable to create the tag set and then return false from the hook function Ensure you consume the ChangeTagAfterDelete hook to carry out custom deletion actions as context called by AbstractContent::getParserOutput May be used to override the normal model specific rendering of page content as context as context the output can only depend on parameters provided to this hook not on global state indicating whether full HTML should be generated If generation of HTML may be but other information should still be present in the ParserOutput object to manipulate or replace but no entry for that model exists in $wgContentHandlers please use GetContentModels hook to make them known to core if desired 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 inclusive $limit
Definition hooks.txt:1143
this hook is for auditing only RecentChangesLinked and Watchlist RecentChangesLinked and Watchlist Do not use this to implement individual filters if they are compatible with the ChangesListFilter and ChangesListFilterGroup structure use sub classes of those in conjunction with the ChangesListSpecialPageStructuredFilters hook This hook can be used to implement filters that do not implement that or custom behavior that is not an individual filter e g Watchlist and Watchlist you will want to construct new ChangesListBooleanFilter or ChangesListStringOptionsFilter objects When constructing you specify which group they belong to You can reuse existing or create your you must register them with $special registerFilterGroup removed from all revisions and log entries to which it was applied This gives extensions a chance to take it off their books as the deletion has already been partly carried out by this point or something similar the user will be unable to create the tag set and then return false from the hook function Ensure you consume the ChangeTagAfterDelete hook to carry out custom deletion actions as context called by AbstractContent::getParserOutput May be used to override the normal model specific rendering of page content as context as context $options
Definition hooks.txt:1102
this hook is for auditing only RecentChangesLinked and Watchlist RecentChangesLinked and Watchlist Do not use this to implement individual filters if they are compatible with the ChangesListFilter and ChangesListFilterGroup structure use sub classes of those in conjunction with the ChangesListSpecialPageStructuredFilters hook This hook can be used to implement filters that do not implement that or custom behavior that is not an individual filter e g Watchlist and Watchlist you will want to construct new ChangesListBooleanFilter or ChangesListStringOptionsFilter objects When constructing you specify which group they belong to You can reuse existing or create your you must register them with $special registerFilterGroup removed from all revisions and log entries to which it was applied This gives extensions a chance to take it off their books as the deletion has already been partly carried out by this point or something similar the user will be unable to create the tag set and then return false from the hook function Ensure you consume the ChangeTagAfterDelete hook to carry out custom deletion actions as context called by AbstractContent::getParserOutput May be used to override the normal model specific rendering of page content $content
Definition hooks.txt:1100
namespace and then decline to actually register it file or subcat img or subcat $title
Definition hooks.txt:964
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 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;div ...>$1&lt;/div>"). - flags Integer display flags(NO_ACTION_LINK, NO_EXTRA_USER_LINKS) 'LogException':Called before an exception(or PHP error) is logged. This is meant for integration with external error aggregation services
do that in ParserLimitReportFormat instead use this to modify the parameters of the image and a DIV can begin in one section and end in another Make sure your code can handle that case gracefully See the EditSectionClearerLink extension for an example zero but section is usually empty & $sectionContent
Definition hooks.txt:2555
null for the local wiki Added in
Definition hooks.txt:1572
it s the revision text itself In either if gzip is the revision text is gzipped $flags
Definition hooks.txt:2753
error also a ContextSource you ll probably need to make sure the header is varied on $request
Definition hooks.txt:2723
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:864
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:1974
usually copyright or history_copyright This message must be in HTML not wikitext & $link
Definition hooks.txt:2937
Using a hook running we can avoid having all this option specific stuff in our mainline code Using the function array $article
Definition hooks.txt:78
this hook is for auditing only RecentChangesLinked and Watchlist RecentChangesLinked and Watchlist Do not use this to implement individual filters if they are compatible with the ChangesListFilter and ChangesListFilterGroup structure use sub classes of those in conjunction with the ChangesListSpecialPageStructuredFilters hook This hook can be used to implement filters that do not implement that or custom behavior that is not an individual filter e g Watchlist and Watchlist you will want to construct new ChangesListBooleanFilter or ChangesListStringOptionsFilter objects When constructing you specify which group they belong to You can reuse existing or create your you must register them with $special registerFilterGroup removed from all revisions and log entries to which it was applied This gives extensions a chance to take it off their books as the deletion has already been partly carried out by this point or something similar the user will be unable to create the tag set $status
Definition hooks.txt:1049
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:903
null for the local 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:1601
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:1751
returning false will NOT prevent logging $e
Definition hooks.txt:2127
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:37
Base interface for content objects.
Definition Content.php:34
Interface for objects which can provide a MediaWiki context on request.
Interface for type hinting (accepts WikiPage, Article, ImagePage, CategoryPage)
Definition Page.php:24
$cache
Definition mcc.php:33
const DB_REPLICA
Definition defines.php:25
if(!isset( $args[0])) $lang