summaryrefslogtreecommitdiff
path: root/includes/page
diff options
context:
space:
mode:
authorPierre Schmitz <pierre@archlinux.de>2015-06-04 07:31:04 +0200
committerPierre Schmitz <pierre@archlinux.de>2015-06-04 07:58:39 +0200
commitf6d65e533c62f6deb21342d4901ece24497b433e (patch)
treef28adf0362d14bcd448f7b65a7aaf38650f923aa /includes/page
parentc27b2e832fe25651ef2410fae85b41072aae7519 (diff)
Update to MediaWiki 1.25.1
Diffstat (limited to 'includes/page')
-rw-r--r--includes/page/Article.php350
-rw-r--r--includes/page/CategoryPage.php6
-rw-r--r--includes/page/ImagePage.php100
-rw-r--r--includes/page/WikiPage.php476
4 files changed, 456 insertions, 476 deletions
diff --git a/includes/page/Article.php b/includes/page/Article.php
index 4e753817..4cde5ad8 100644
--- a/includes/page/Article.php
+++ b/includes/page/Article.php
@@ -30,8 +30,6 @@
* See design.txt for an overview.
* Note: edit user interface and cache support functions have been
* moved to separate EditPage and HTMLFileCache classes.
- *
- * @internal documentation reviewed 15 Mar 2010
*/
class Article implements Page {
/** @var IContextSource The context this Article is executed in */
@@ -120,7 +118,7 @@ class Article implements Page {
}
$page = null;
- wfRunHooks( 'ArticleFromTitle', array( &$title, &$page, $context ) );
+ Hooks::run( 'ArticleFromTitle', array( &$title, &$page, $context ) );
if ( !$page ) {
switch ( $title->getNamespace() ) {
case NS_FILE:
@@ -226,7 +224,6 @@ class Article implements Page {
* @since 1.21
*/
protected function getContentObject() {
- wfProfileIn( __METHOD__ );
if ( $this->mPage->getID() === 0 ) {
# If this is a MediaWiki:x message, then load the messages
@@ -247,7 +244,6 @@ class Article implements Page {
$content = $this->mContentObject;
}
- wfProfileOut( __METHOD__ );
return $content;
}
@@ -344,12 +340,9 @@ class Article implements Page {
return $this->mContent;
}
- wfProfileIn( __METHOD__ );
-
$content = $this->fetchContentObject();
if ( !$content ) {
- wfProfileOut( __METHOD__ );
return false;
}
@@ -357,8 +350,6 @@ class Article implements Page {
$this->mContent = ContentHandler::getContentText( $content );
ContentHandler::runLegacyHooks( 'ArticleAfterFetchContent', array( &$this, &$this->mContent ) );
- wfProfileOut( __METHOD__ );
-
return $this->mContent;
}
@@ -379,8 +370,6 @@ class Article implements Page {
return $this->mContentObject;
}
- wfProfileIn( __METHOD__ );
-
$this->mContentLoaded = true;
$this->mContent = null;
@@ -389,7 +378,7 @@ class Article implements Page {
# Pre-fill content with error message so that if something
# fails we'll have something telling us what we intended.
//XXX: this isn't page content but a UI message. horrible.
- $this->mContentObject = new MessageContent( 'missing-revision', array( $oldid ), array() );
+ $this->mContentObject = new MessageContent( 'missing-revision', array( $oldid ) );
if ( $oldid ) {
# $this->mRevision might already be fetched by getOldIDFromRequest()
@@ -397,24 +386,24 @@ class Article implements Page {
$this->mRevision = Revision::newFromId( $oldid );
if ( !$this->mRevision ) {
wfDebug( __METHOD__ . " failed to retrieve specified revision, id $oldid\n" );
- wfProfileOut( __METHOD__ );
return false;
}
}
} else {
- if ( !$this->mPage->getLatest() ) {
+ $oldid = $this->mPage->getLatest();
+ if ( !$oldid ) {
wfDebug( __METHOD__ . " failed to find page data for title " .
$this->getTitle()->getPrefixedText() . "\n" );
- wfProfileOut( __METHOD__ );
return false;
}
+ # Update error message with correct oldid
+ $this->mContentObject = new MessageContent( 'missing-revision', array( $oldid ) );
+
$this->mRevision = $this->mPage->getRevision();
if ( !$this->mRevision ) {
- wfDebug( __METHOD__ . " failed to retrieve current page, rev_id " .
- $this->mPage->getLatest() . "\n" );
- wfProfileOut( __METHOD__ );
+ wfDebug( __METHOD__ . " failed to retrieve current page, rev_id $oldid\n" );
return false;
}
}
@@ -422,15 +411,21 @@ class Article implements Page {
// @todo FIXME: Horrible, horrible! This content-loading interface just plain sucks.
// We should instead work with the Revision object when we need it...
// Loads if user is allowed
- $this->mContentObject = $this->mRevision->getContent(
+ $content = $this->mRevision->getContent(
Revision::FOR_THIS_USER,
$this->getContext()->getUser()
);
- $this->mRevIdFetched = $this->mRevision->getId();
- wfRunHooks( 'ArticleAfterFetchContentObject', array( &$this, &$this->mContentObject ) );
+ if ( !$content ) {
+ wfDebug( __METHOD__ . " failed to retrieve content of revision " .
+ $this->mRevision->getId() . "\n" );
+ return false;
+ }
+
+ $this->mContentObject = $content;
+ $this->mRevIdFetched = $this->mRevision->getId();
- wfProfileOut( __METHOD__ );
+ Hooks::run( 'ArticleAfterFetchContentObject', array( &$this, &$this->mContentObject ) );
return $this->mContentObject;
}
@@ -482,8 +477,6 @@ class Article implements Page {
public function view() {
global $wgUseFileCache, $wgUseETag, $wgDebugToolbar, $wgMaxRedirects;
- wfProfileIn( __METHOD__ );
-
# Get variables from query string
# As side effect this will load the revision and update the title
# in a revision ID is passed in the request, so this should remain
@@ -495,7 +488,6 @@ class Article implements Page {
$permErrors = $this->getTitle()->getUserPermissionsErrors( 'read', $user );
if ( count( $permErrors ) ) {
wfDebug( __METHOD__ . ": denied on secondary read check\n" );
- wfProfileOut( __METHOD__ );
throw new PermissionsError( 'read', $permErrors );
}
@@ -504,7 +496,6 @@ class Article implements Page {
if ( $this->mRedirectUrl ) {
$outputPage->redirect( $this->mRedirectUrl );
wfDebug( __METHOD__ . ": redirecting due to oldid\n" );
- wfProfileOut( __METHOD__ );
return;
}
@@ -513,7 +504,6 @@ class Article implements Page {
if ( $this->getContext()->getRequest()->getCheck( 'diff' ) ) {
wfDebug( __METHOD__ . ": showing diff page\n" );
$this->showDiffPage();
- wfProfileOut( __METHOD__ );
return;
}
@@ -568,7 +558,6 @@ class Article implements Page {
# Is it client cached?
if ( $outputPage->checkLastModified( $timestamp ) ) {
wfDebug( __METHOD__ . ": done 304\n" );
- wfProfileOut( __METHOD__ );
return;
# Try file cache
@@ -577,7 +566,6 @@ class Article implements Page {
# tell wgOut that output is taken care of
$outputPage->disable();
$this->mPage->doViewUpdates( $user, $oldid );
- wfProfileOut( __METHOD__ );
return;
}
@@ -587,7 +575,7 @@ class Article implements Page {
$useParserCache = $this->mPage->isParserCacheUsed( $parserOptions, $oldid );
wfDebug( 'Article::view using parser cache: ' . ( $useParserCache ? 'yes' : 'no' ) . "\n" );
if ( $user->getStubThreshold() ) {
- wfIncrStats( 'pcache_miss_stub' );
+ $this->getContext()->getStats()->increment( 'pcache_miss_stub' );
}
$this->showRedirectedFromHeader();
@@ -602,7 +590,7 @@ class Article implements Page {
while ( !$outputDone && ++$pass ) {
switch ( $pass ) {
case 1:
- wfRunHooks( 'ArticleViewHeader', array( &$this, &$outputDone, &$useParserCache ) );
+ Hooks::run( 'ArticleViewHeader', array( &$this, &$outputDone, &$useParserCache ) );
break;
case 2:
# Early abort if the page doesn't exist
@@ -610,7 +598,6 @@ class Article implements Page {
wfDebug( __METHOD__ . ": showing missing article\n" );
$this->showMissingArticle();
$this->mPage->doViewUpdates( $user );
- wfProfileOut( __METHOD__ );
return;
}
@@ -649,7 +636,6 @@ class Article implements Page {
if ( !$this->showDeletedRevisionHeader() ) {
wfDebug( __METHOD__ . ": cannot view deleted revision\n" );
- wfProfileOut( __METHOD__ );
return;
}
}
@@ -665,7 +651,7 @@ class Article implements Page {
wfDebug( __METHOD__ . ": showing CSS/JS source\n" );
$this->showCssOrJsPage();
$outputDone = true;
- } elseif ( !wfRunHooks( 'ArticleContentViewCustom',
+ } elseif ( !Hooks::run( 'ArticleContentViewCustom',
array( $this->fetchContentObject(), $this->getTitle(), $outputPage ) ) ) {
# Allow extensions do their own custom view for certain pages
@@ -696,16 +682,14 @@ class Article implements Page {
$outputPage->addWikiText( '<div class="errorbox">' . $errortext . '</div>' );
}
# Connection or timeout error
- wfProfileOut( __METHOD__ );
return;
}
$this->mParserOutput = $poolArticleView->getParserOutput();
$outputPage->addParserOutput( $this->mParserOutput );
if ( $content->getRedirectTarget() ) {
- $outputPage->addSubtitle(
- "<span id=\"redirectsub\">" . wfMessage( 'redirectpagesub' )->parse() . "</span>"
- );
+ $outputPage->addSubtitle( "<span id=\"redirectsub\">" .
+ $this->getContext()->msg( 'redirectpagesub' )->parse() . "</span>" );
}
# Don't cache a dirty ParserOutput object
@@ -724,7 +708,7 @@ class Article implements Page {
}
# Get the ParserOutput actually *displayed* here.
- # Note that $this->mParserOutput is the *current* version output.
+ # Note that $this->mParserOutput is the *current*/oldid version output.
$pOutput = ( $outputDone instanceof ParserOutput )
? $outputDone // object fetched by hook
: $this->mParserOutput;
@@ -755,7 +739,6 @@ class Article implements Page {
$outputPage->addModules( 'mediawiki.action.view.postEdit' );
- wfProfileOut( __METHOD__ );
}
/**
@@ -774,9 +757,8 @@ class Article implements Page {
* Show a diff page according to current request variables. For use within
* Article::view() only, other callers should use the DifferenceEngine class.
*
- * @todo Make protected
*/
- public function showDiffPage() {
+ protected function showDiffPage() {
$request = $this->getContext()->getRequest();
$user = $this->getContext()->getUser();
$diff = $request->getVal( 'diff' );
@@ -790,7 +772,11 @@ class Article implements Page {
if ( !$rev ) {
$this->getContext()->getOutput()->setPageTitle( wfMessage( 'errorpagetitle' ) );
- $this->getContext()->getOutput()->addWikiMsg( 'difference-missing-revision', $oldid, 1 );
+ $msg = $this->getContext()->msg( 'difference-missing-revision' )
+ ->params( $oldid )
+ ->numParams( 1 )
+ ->parseAsBlock();
+ $this->getContext()->getOutput()->addHtml( $msg );
return;
}
@@ -831,7 +817,7 @@ class Article implements Page {
if ( $showCacheHint ) {
$dir = $this->getContext()->getLanguage()->getDir();
- $lang = $this->getContext()->getLanguage()->getCode();
+ $lang = $this->getContext()->getLanguage()->getHtmlCode();
$outputPage->wrapWikiMsg(
"<div id='mw-clearyourcache' lang='$lang' dir='$dir' class='mw-content-$dir'>\n$1\n</div>",
@@ -973,9 +959,10 @@ class Article implements Page {
*/
public function showRedirectedFromHeader() {
global $wgRedirectSources;
- $outputPage = $this->getContext()->getOutput();
- $request = $this->getContext()->getRequest();
+ $context = $this->getContext();
+ $outputPage = $context->getOutput();
+ $request = $context->getRequest();
$rdfrom = $request->getVal( 'rdfrom' );
// Construct a URL for the current page view, but with the target title
@@ -991,7 +978,7 @@ class Article implements Page {
if ( isset( $this->mRedirectedFrom ) ) {
// This is an internally redirected page view.
// We'll need a backlink to the source page for navigation.
- if ( wfRunHooks( 'ArticleViewRedirect', array( &$this ) ) ) {
+ if ( Hooks::run( 'ArticleViewRedirect', array( &$this ) ) ) {
$redir = Linker::linkKnown(
$this->mRedirectedFrom,
null,
@@ -999,7 +986,9 @@ class Article implements Page {
array( 'redirect' => 'no' )
);
- $outputPage->addSubtitle( wfMessage( 'redirectedfrom' )->rawParams( $redir ) );
+ $outputPage->addSubtitle( "<span class=\"mw-redirectedfrom\">" .
+ $context->msg( 'redirectedfrom' )->rawParams( $redir )->parse()
+ . "</span>" );
// Add the script to update the displayed URL and
// set the fragment if one was specified in the redirect
@@ -1021,7 +1010,9 @@ class Article implements Page {
// If it was reported from a trusted site, supply a backlink.
if ( $wgRedirectSources && preg_match( $wgRedirectSources, $rdfrom ) ) {
$redir = Linker::makeExternalLink( $rdfrom, $rdfrom );
- $outputPage->addSubtitle( wfMessage( 'redirectedfrom' )->rawParams( $redir ) );
+ $outputPage->addSubtitle( "<span class=\"mw-redirectedfrom\">" .
+ $context->msg( 'redirectedfrom' )->rawParams( $redir )->parse()
+ . "</span>" );
// Add the script to update the displayed URL
$outputPage->addJsConfigVars( array(
@@ -1065,7 +1056,7 @@ class Article implements Page {
// Show a footer allowing the user to patrol the shown revision or page if possible
$patrolFooterShown = $this->showPatrolFooter();
- wfRunHooks( 'ArticleViewFooter', array( $this, $patrolFooterShown ) );
+ Hooks::run( 'ArticleViewFooter', array( $this, $patrolFooterShown ) );
}
/**
@@ -1092,8 +1083,6 @@ class Article implements Page {
return false;
}
- wfProfileIn( __METHOD__ );
-
// New page patrol: Get the timestamp of the oldest revison which
// the revision table holds for the given page. Then we look
// whether it's within the RC lifespan and if it is, we try
@@ -1102,7 +1091,6 @@ class Article implements Page {
// Check for cached results
if ( $cache->get( wfMemcKey( 'NotPatrollablePage', $this->getTitle()->getArticleID() ) ) ) {
- wfProfileOut( __METHOD__ );
return false;
}
@@ -1111,7 +1099,6 @@ class Article implements Page {
) {
// The current revision is already older than what could be in the RC table
// 6h tolerance because the RC might not be cleaned out regularly
- wfProfileOut( __METHOD__ );
return false;
}
@@ -1147,14 +1134,12 @@ class Article implements Page {
// Don't cache in case we can patrol as this could change
$cache->set( wfMemcKey( 'NotPatrollablePage', $this->getTitle()->getArticleID() ), '1' );
- wfProfileOut( __METHOD__ );
return false;
}
- if ( $rc->getPerformer()->getName() == $user->getName() ) {
+ if ( $rc->getPerformer()->equals( $user ) ) {
// Don't show a patrol link for own creations. If the user could
// patrol them, they already would be patrolled
- wfProfileOut( __METHOD__ );
return false;
}
@@ -1184,7 +1169,6 @@ class Article implements Page {
'</div>'
);
- wfProfileOut( __METHOD__ );
return true;
}
@@ -1214,7 +1198,8 @@ class Article implements Page {
if ( !( $user && $user->isLoggedIn() ) && !$ip ) { # User does not exist
$outputPage->wrapWikiMsg( "<div class=\"mw-userpage-userdoesnotexist error\">\n\$1\n</div>",
array( 'userpage-userdoesnotexist-view', wfEscapeWikiText( $rootPart ) ) );
- } elseif ( !is_null( $block ) && $block->getType() != Block::TYPE_AUTO ) { # Show log extract if the user is currently blocked
+ } elseif ( !is_null( $block ) && $block->getType() != Block::TYPE_AUTO ) {
+ # Show log extract if the user is currently blocked
LogEventsList::showLogExtract(
$outputPage,
'block',
@@ -1235,24 +1220,20 @@ class Article implements Page {
}
}
- wfRunHooks( 'ShowMissingArticle', array( $this ) );
+ Hooks::run( 'ShowMissingArticle', array( $this ) );
// Give extensions a chance to hide their (unrelated) log entries
$logTypes = array( 'delete', 'move' );
$conds = array( "log_action != 'revision'" );
- wfRunHooks( 'Article::MissingArticleConditions', array( &$conds, $logTypes ) );
+ Hooks::run( 'Article::MissingArticleConditions', array( &$conds, $logTypes ) );
# Show delete and move logs
- $member = $title->getNamespace() . ':' . $title->getDBkey();
- // @todo: move optimization to showLogExtract()?
- if ( BloomCache::get( 'main' )->check( wfWikiId(), 'TitleHasLogs', $member ) ) {
- LogEventsList::showLogExtract( $outputPage, $logTypes, $title, '',
- array( 'lim' => 10,
- 'conds' => $conds,
- 'showIfEmpty' => false,
- 'msgKey' => array( 'moveddeleted-notice' ) )
- );
- }
+ LogEventsList::showLogExtract( $outputPage, $logTypes, $title, '',
+ array( 'lim' => 10,
+ 'conds' => $conds,
+ 'showIfEmpty' => false,
+ 'msgKey' => array( 'moveddeleted-notice' ) )
+ );
if ( !$this->mPage->hasViewableContent() && $wgSend404Code && !$validUserPage ) {
// If there's no backing content, send a 404 Not Found
@@ -1265,7 +1246,7 @@ class Article implements Page {
$outputPage->setIndexPolicy( $policy['index'] );
$outputPage->setFollowPolicy( $policy['follow'] );
- $hookResult = wfRunHooks( 'BeforeDisplayNoArticleText', array( $this ) );
+ $hookResult = Hooks::run( 'BeforeDisplayNoArticleText', array( $this ) );
if ( !$hookResult ) {
return;
@@ -1341,11 +1322,12 @@ class Article implements Page {
* @param int $oldid Revision ID of this article revision
*/
public function setOldSubtitle( $oldid = 0 ) {
- if ( !wfRunHooks( 'DisplayOldSubtitle', array( &$this, &$oldid ) ) ) {
+ if ( !Hooks::run( 'DisplayOldSubtitle', array( &$this, &$oldid ) ) ) {
return;
}
- $unhide = $this->getContext()->getRequest()->getInt( 'unhide' ) == 1;
+ $context = $this->getContext();
+ $unhide = $context->getRequest()->getInt( 'unhide' ) == 1;
# Cascade unhide param in links for easy deletion browsing
$extraParams = array();
@@ -1362,8 +1344,8 @@ class Article implements Page {
$timestamp = $revision->getTimestamp();
$current = ( $oldid == $this->mPage->getLatest() );
- $language = $this->getContext()->getLanguage();
- $user = $this->getContext()->getUser();
+ $language = $context->getLanguage();
+ $user = $context->getUser();
$td = $language->userTimeAndDate( $timestamp, $user );
$tddate = $language->userDate( $timestamp, $user );
@@ -1372,28 +1354,33 @@ class Article implements Page {
# Show user links if allowed to see them. If hidden, then show them only if requested...
$userlinks = Linker::revUserTools( $revision, !$unhide );
- $infomsg = $current && !wfMessage( 'revision-info-current' )->isDisabled()
+ $infomsg = $current && !$context->msg( 'revision-info-current' )->isDisabled()
? 'revision-info-current'
: 'revision-info';
- $outputPage = $this->getContext()->getOutput();
- $outputPage->addSubtitle( "<div id=\"mw-{$infomsg}\">" . wfMessage( $infomsg,
- $td )->rawParams( $userlinks )->params( $revision->getID(), $tddate,
- $tdtime, $revision->getUserText() )->rawParams( Linker::revComment( $revision, true, true ) )->parse() . "</div>" );
+ $outputPage = $context->getOutput();
+ $outputPage->addSubtitle( "<div id=\"mw-{$infomsg}\">" .
+ $context->msg( $infomsg, $td )
+ ->rawParams( $userlinks )
+ ->params( $revision->getID(), $tddate, $tdtime, $revision->getUserText() )
+ ->rawParams( Linker::revComment( $revision, true, true ) )
+ ->parse() .
+ "</div>"
+ );
$lnk = $current
- ? wfMessage( 'currentrevisionlink' )->escaped()
+ ? $context->msg( 'currentrevisionlink' )->escaped()
: Linker::linkKnown(
$this->getTitle(),
- wfMessage( 'currentrevisionlink' )->escaped(),
+ $context->msg( 'currentrevisionlink' )->escaped(),
array(),
$extraParams
);
$curdiff = $current
- ? wfMessage( 'diff' )->escaped()
+ ? $context->msg( 'diff' )->escaped()
: Linker::linkKnown(
$this->getTitle(),
- wfMessage( 'diff' )->escaped(),
+ $context->msg( 'diff' )->escaped(),
array(),
array(
'diff' => 'cur',
@@ -1404,30 +1391,30 @@ class Article implements Page {
$prevlink = $prev
? Linker::linkKnown(
$this->getTitle(),
- wfMessage( 'previousrevision' )->escaped(),
+ $context->msg( 'previousrevision' )->escaped(),
array(),
array(
'direction' => 'prev',
'oldid' => $oldid
) + $extraParams
)
- : wfMessage( 'previousrevision' )->escaped();
+ : $context->msg( 'previousrevision' )->escaped();
$prevdiff = $prev
? Linker::linkKnown(
$this->getTitle(),
- wfMessage( 'diff' )->escaped(),
+ $context->msg( 'diff' )->escaped(),
array(),
array(
'diff' => 'prev',
'oldid' => $oldid
) + $extraParams
)
- : wfMessage( 'diff' )->escaped();
+ : $context->msg( 'diff' )->escaped();
$nextlink = $current
- ? wfMessage( 'nextrevision' )->escaped()
+ ? $context->msg( 'nextrevision' )->escaped()
: Linker::linkKnown(
$this->getTitle(),
- wfMessage( 'nextrevision' )->escaped(),
+ $context->msg( 'nextrevision' )->escaped(),
array(),
array(
'direction' => 'next',
@@ -1435,10 +1422,10 @@ class Article implements Page {
) + $extraParams
);
$nextdiff = $current
- ? wfMessage( 'diff' )->escaped()
+ ? $context->msg( 'diff' )->escaped()
: Linker::linkKnown(
$this->getTitle(),
- wfMessage( 'diff' )->escaped(),
+ $context->msg( 'diff' )->escaped(),
array(),
array(
'diff' => 'next',
@@ -1452,7 +1439,7 @@ class Article implements Page {
}
$outputPage->addSubtitle( "<div id=\"mw-revision-nav\">" . $cdel .
- wfMessage( 'revision-nav' )->rawParams(
+ $context->msg( 'revision-nav' )->rawParams(
$prevdiff, $prevlink, $lnk, $curdiff, $nextlink, $nextdiff
)->escaped() . "</div>" );
}
@@ -1472,7 +1459,7 @@ class Article implements Page {
$lang = $this->getTitle()->getPageLanguage();
$out = $this->getContext()->getOutput();
if ( $appendSubtitle ) {
- $out->addSubtitle( wfMessage( 'redirectpagesub' )->parse() );
+ $out->addSubtitle( wfMessage( 'redirectpagesub' ) );
}
$out->addModuleStyles( 'mediawiki.action.view.redirectPage' );
return static::getRedirectHeaderHtml( $lang, $target, $forceKnown );
@@ -1508,8 +1495,9 @@ class Article implements Page {
( $forceKnown ? array( 'known', 'noclasses' ) : array() )
) . '</li>';
}
+ $html .= '</ul>';
- $redirectToText = wfMessage( 'redirectto' )->inLanguage( $lang )->text();
+ $redirectToText = wfMessage( 'redirectto' )->inLanguage( $lang )->escaped();
return '<div class="redirectMsg">' .
'<p>' . $redirectToText . '</p>' .
@@ -1518,6 +1506,28 @@ class Article implements Page {
}
/**
+ * Adds help link with an icon via page indicators.
+ * Link target can be overridden by a local message containing a wikilink:
+ * the message key is: 'namespace-' + namespace number + '-helppage'.
+ * @param string $to Target MediaWiki.org page title or encoded URL.
+ * @param bool $overrideBaseUrl Whether $url is a full URL, to avoid MW.o.
+ * @since 1.25
+ */
+ public function addHelpLink( $to, $overrideBaseUrl = false ) {
+ $msg = wfMessage(
+ 'namespace-' . $this->getTitle()->getNamespace() . '-helppage'
+ );
+
+ $out = $this->getContext()->getOutput();
+ if ( !$msg->isDisabled() ) {
+ $helpUrl = Skin::makeUrl( $msg->plain() );
+ $out->addHelpLink( $helpUrl, true );
+ } else {
+ $out->addHelpLink( $to, $overrideBaseUrl );
+ }
+ }
+
+ /**
* Handle action=render
*/
public function render() {
@@ -1549,7 +1559,8 @@ class Article implements Page {
# This code desperately needs to be totally rewritten
$title = $this->getTitle();
- $user = $this->getContext()->getUser();
+ $context = $this->getContext();
+ $user = $context->getUser();
# Check permissions
$permissionErrors = $title->getUserPermissionsErrors( 'delete', $user );
@@ -1566,8 +1577,8 @@ class Article implements Page {
$this->mPage->loadPageData( 'fromdbmaster' );
if ( !$this->mPage->exists() ) {
$deleteLogPage = new LogPage( 'delete' );
- $outputPage = $this->getContext()->getOutput();
- $outputPage->setPageTitle( wfMessage( 'cannotdelete-title', $title->getPrefixedText() ) );
+ $outputPage = $context->getOutput();
+ $outputPage->setPageTitle( $context->msg( 'cannotdelete-title', $title->getPrefixedText() ) );
$outputPage->wrapWikiMsg( "<div class=\"error mw-error-cannotdelete\">\n$1\n</div>",
array( 'cannotdelete', wfEscapeWikiText( $title->getPrefixedText() ) )
);
@@ -1583,7 +1594,7 @@ class Article implements Page {
return;
}
- $request = $this->getContext()->getRequest();
+ $request = $context->getRequest();
$deleteReasonList = $request->getText( 'wpDeleteReasonList', 'other' );
$deleteReason = $request->getText( 'wpReason' );
@@ -1615,7 +1626,7 @@ class Article implements Page {
if ( !$reason ) {
try {
$reason = $this->generateReason( $hasHistory );
- } catch ( MWException $e ) {
+ } catch ( Exception $e ) {
# if a page is horribly broken, we still want to be able to
# delete it. So be lenient about errors here.
wfDebug( "Error while building auto delete summary: $e" );
@@ -1627,10 +1638,11 @@ class Article implements Page {
if ( $hasHistory ) {
$title = $this->getTitle();
- // The following can use the real revision count as this is only being shown for users that can delete
- // this page.
- // This, as a side-effect, also makes sure that the following query isn't being run for pages with a
- // larger history, unless the user has the 'bigdelete' right (and is about to delete this page).
+ // The following can use the real revision count as this is only being shown for users
+ // that can delete this page.
+ // This, as a side-effect, also makes sure that the following query isn't being run for
+ // pages with a larger history, unless the user has the 'bigdelete' right
+ // (and is about to delete this page).
$dbr = wfGetDB( DB_SLAVE );
$revisions = $edits = (int)$dbr->selectField(
'revision',
@@ -1640,21 +1652,22 @@ class Article implements Page {
);
// @todo FIXME: i18n issue/patchwork message
- $this->getContext()->getOutput()->addHTML( '<strong class="mw-delete-warning-revisions">' .
- wfMessage( 'historywarning' )->numParams( $revisions )->parse() .
- wfMessage( 'word-separator' )->plain() . Linker::linkKnown( $title,
- wfMessage( 'history' )->escaped(),
- array( 'rel' => 'archives' ),
+ $context->getOutput()->addHTML(
+ '<strong class="mw-delete-warning-revisions">' .
+ $context->msg( 'historywarning' )->numParams( $revisions )->parse() .
+ $context->msg( 'word-separator' )->escaped() . Linker::linkKnown( $title,
+ $context->msg( 'history' )->escaped(),
+ array(),
array( 'action' => 'history' ) ) .
'</strong>'
);
if ( $title->isBigDeletion() ) {
global $wgDeleteRevisionsLimit;
- $this->getContext()->getOutput()->wrapWikiMsg( "<div class='error'>\n$1\n</div>\n",
+ $context->getOutput()->wrapWikiMsg( "<div class='error'>\n$1\n</div>\n",
array(
'delete-warning-toobig',
- $this->getContext()->getLanguage()->formatNum( $wgDeleteRevisionsLimit )
+ $context->getLanguage()->formatNum( $wgDeleteRevisionsLimit )
)
);
}
@@ -1672,7 +1685,9 @@ class Article implements Page {
wfDebug( "Article::confirmDelete\n" );
$title = $this->getTitle();
- $outputPage = $this->getContext()->getOutput();
+ $ctx = $this->getContext();
+ $outputPage = $ctx->getOutput();
+ $useMediaWikiUIEverywhere = $ctx->getConfig()->get( 'UseMediaWikiUIEverywhere' );
$outputPage->setPageTitle( wfMessage( 'delete-confirm', $title->getPrefixedText() ) );
$outputPage->addBacklinkSubtitle( $title );
$outputPage->setRobotPolicy( 'noindex,nofollow' );
@@ -1683,80 +1698,72 @@ class Article implements Page {
}
$outputPage->addWikiMsg( 'confirmdeletetext' );
- wfRunHooks( 'ArticleConfirmDelete', array( $this, $outputPage, &$reason ) );
+ Hooks::run( 'ArticleConfirmDelete', array( $this, $outputPage, &$reason ) );
$user = $this->getContext()->getUser();
if ( $user->isAllowed( 'suppressrevision' ) ) {
- $suppress = "<tr id=\"wpDeleteSuppressRow\">
- <td></td>
- <td class='mw-input'><strong>" .
+ $suppress = Html::openElement( 'div', array( 'id' => 'wpDeleteSuppressRow' ) ) .
+ "<strong>" .
Xml::checkLabel( wfMessage( 'revdelete-suppress' )->text(),
'wpSuppress', 'wpSuppress', false, array( 'tabindex' => '4' ) ) .
- "</strong></td>
- </tr>";
+ "</strong>" .
+ Html::closeElement( 'div' );
} else {
$suppress = '';
}
$checkWatch = $user->getBoolOption( 'watchdeletion' ) || $user->isWatched( $title );
- $form = Xml::openElement( 'form', array( 'method' => 'post',
+ $form = Html::openElement( 'form', array( 'method' => 'post',
'action' => $title->getLocalURL( 'action=delete' ), 'id' => 'deleteconfirm' ) ) .
- Xml::openElement( 'fieldset', array( 'id' => 'mw-delete-table' ) ) .
- Xml::tags( 'legend', null, wfMessage( 'delete-legend' )->escaped() ) .
- Xml::openElement( 'table', array( 'id' => 'mw-deleteconfirm-table' ) ) .
- "<tr id=\"wpDeleteReasonListRow\">
- <td class='mw-label'>" .
- Xml::label( wfMessage( 'deletecomment' )->text(), 'wpDeleteReasonList' ) .
- "</td>
- <td class='mw-input'>" .
- Xml::listDropDown(
- 'wpDeleteReasonList',
- wfMessage( 'deletereason-dropdown' )->inContentLanguage()->text(),
- wfMessage( 'deletereasonotherlist' )->inContentLanguage()->text(),
- '',
- 'wpReasonDropDown',
- 1
- ) .
- "</td>
- </tr>
- <tr id=\"wpDeleteReasonRow\">
- <td class='mw-label'>" .
- Xml::label( wfMessage( 'deleteotherreason' )->text(), 'wpReason' ) .
- "</td>
- <td class='mw-input'>" .
- Html::input( 'wpReason', $reason, 'text', array(
- 'size' => '60',
- 'maxlength' => '255',
- 'tabindex' => '2',
- 'id' => 'wpReason',
- 'autofocus'
- ) ) .
- "</td>
- </tr>";
+ Html::openElement( 'fieldset', array( 'id' => 'mw-delete-table' ) ) .
+ Html::element( 'legend', null, wfMessage( 'delete-legend' )->text() ) .
+ Html::openElement( 'div', array( 'id' => 'mw-deleteconfirm-table' ) ) .
+ Html::openElement( 'div', array( 'id' => 'wpDeleteReasonListRow' ) ) .
+ Html::label( wfMessage( 'deletecomment' )->text(), 'wpDeleteReasonList' ) .
+ '&nbsp;' .
+ Xml::listDropDown(
+ 'wpDeleteReasonList',
+ wfMessage( 'deletereason-dropdown' )->inContentLanguage()->text(),
+ wfMessage( 'deletereasonotherlist' )->inContentLanguage()->text(),
+ '',
+ 'wpReasonDropDown',
+ 1
+ ) .
+ Html::closeElement( 'div' ) .
+ Html::openElement( 'div', array( 'id' => 'wpDeleteReasonRow' ) ) .
+ Html::label( wfMessage( 'deleteotherreason' )->text(), 'wpReason' ) .
+ '&nbsp;' .
+ Html::input( 'wpReason', $reason, 'text', array(
+ 'size' => '60',
+ 'maxlength' => '255',
+ 'tabindex' => '2',
+ 'id' => 'wpReason',
+ 'class' => 'mw-ui-input-inline',
+ 'autofocus'
+ ) ) .
+ Html::closeElement( 'div' );
# Disallow watching if user is not logged in
if ( $user->isLoggedIn() ) {
- $form .= "
- <tr>
- <td></td>
- <td class='mw-input'>" .
+ $form .=
Xml::checkLabel( wfMessage( 'watchthis' )->text(),
- 'wpWatch', 'wpWatch', $checkWatch, array( 'tabindex' => '3' ) ) .
- "</td>
- </tr>";
+ 'wpWatch', 'wpWatch', $checkWatch, array( 'tabindex' => '3' ) );
}
- $form .= "
- $suppress
- <tr>
- <td></td>
- <td class='mw-submit'>" .
+ $form .=
+ Html::openElement( 'div' ) .
+ $suppress .
Xml::submitButton( wfMessage( 'deletepage' )->text(),
- array( 'name' => 'wpConfirmB', 'id' => 'wpConfirmB', 'tabindex' => '5' ) ) .
- "</td>
- </tr>" .
- Xml::closeElement( 'table' ) .
+ array(
+ 'name' => 'wpConfirmB',
+ 'id' => 'wpConfirmB',
+ 'tabindex' => '5',
+ 'class' => $useMediaWikiUIEverywhere ? 'mw-ui-button mw-ui-destructive' : '',
+ )
+ ) .
+ Html::closeElement( 'div' ) .
+ Html::closeElement( 'div' ) .
Xml::closeElement( 'fieldset' ) .
Html::hidden(
'wpEditToken',
@@ -1801,6 +1808,9 @@ class Article implements Page {
$loglink = '[[Special:Log/delete|' . wfMessage( 'deletionlog' )->text() . ']]';
$outputPage->addWikiMsg( 'deletedtext', wfEscapeWikiText( $deleted ), $loglink );
+
+ Hooks::run( 'ArticleDeleteAfterSuccess', array( $this->getTitle(), $outputPage ) );
+
$outputPage->returnToMain( false );
} else {
$outputPage->setPageTitle(
@@ -1873,7 +1883,7 @@ class Article implements Page {
&& !$this->mRedirectedFrom && !$this->getTitle()->isRedirect();
// Extension may have reason to disable file caching on some pages.
if ( $cacheable ) {
- $cacheable = wfRunHooks( 'IsFileCacheable', array( &$this ) );
+ $cacheable = Hooks::run( 'IsFileCacheable', array( &$this ) );
}
}
diff --git a/includes/page/CategoryPage.php b/includes/page/CategoryPage.php
index 9abc6a89..caebcd7d 100644
--- a/includes/page/CategoryPage.php
+++ b/includes/page/CategoryPage.php
@@ -61,7 +61,7 @@ class CategoryPage extends Article {
return;
}
- if ( !wfRunHooks( 'CategoryPageView', array( &$this ) ) ) {
+ if ( !Hooks::run( 'CategoryPageView', array( &$this ) ) ) {
return;
}
@@ -113,6 +113,8 @@ class CategoryPage extends Article {
$until,
$reqArray
);
- $this->getContext()->getOutput()->addHTML( $viewer->getHTML() );
+ $out = $this->getContext()->getOutput();
+ $out->addHTML( $viewer->getHTML() );
+ $this->addHelpLink( 'Help:Categories' );
}
}
diff --git a/includes/page/ImagePage.php b/includes/page/ImagePage.php
index d06c8191..8f635cfa 100644
--- a/includes/page/ImagePage.php
+++ b/includes/page/ImagePage.php
@@ -76,7 +76,7 @@ class ImagePage extends Article {
$this->fileLoaded = true;
$this->displayImg = $img = false;
- wfRunHooks( 'ImagePageFindFile', array( $this, &$img, &$this->displayImg ) );
+ Hooks::run( 'ImagePageFindFile', array( $this, &$img, &$this->displayImg ) );
if ( !$img ) { // not set by hook?
$img = wfFindFile( $this->getTitle() );
if ( !$img ) {
@@ -140,7 +140,7 @@ class ImagePage extends Article {
if ( $wgShowEXIF && $this->displayImg->exists() ) {
// @todo FIXME: Bad interface, see note on MediaHandler::formatMetadata().
- $formattedMetadata = $this->displayImg->formatMetadata();
+ $formattedMetadata = $this->displayImg->formatMetadata( $this->getContext() );
$showmeta = $formattedMetadata !== false;
} else {
$showmeta = false;
@@ -175,7 +175,7 @@ class ImagePage extends Article {
# Show shared description, if needed
if ( $this->mExtraDescription ) {
- $fol = wfMessage( 'shareddescriptionfollows' );
+ $fol = $this->getContext()->msg( 'shareddescriptionfollows' );
if ( !$fol->isDisabled() ) {
$out->addWikiText( $fol->plain() );
}
@@ -188,7 +188,7 @@ class ImagePage extends Article {
$out->addHTML( Xml::element( 'h2',
array( 'id' => 'filelinks' ),
- wfMessage( 'imagelinks' )->text() ) . "\n" );
+ $this->getContext()->msg( 'imagelinks' )->text() ) . "\n" );
$this->imageDupes();
# @todo FIXME: For some freaky reason, we can't redirect to foreign images.
# Yet we return metadata about the target. Definitely an issue in the FileRepo
@@ -196,7 +196,7 @@ class ImagePage extends Article {
# Allow extensions to add something after the image links
$html = '';
- wfRunHooks( 'ImagePageAfterImageLinks', array( $this, &$html ) );
+ Hooks::run( 'ImagePageAfterImageLinks', array( $this, &$html ) );
if ( $html ) {
$out->addHTML( $html );
}
@@ -205,7 +205,7 @@ class ImagePage extends Article {
$out->addHTML( Xml::element(
'h2',
array( 'id' => 'metadata' ),
- wfMessage( 'metadata' )->text() ) . "\n" );
+ $this->getContext()->msg( 'metadata' )->text() ) . "\n" );
$out->addWikiText( $this->makeMetadataTable( $formattedMetadata ) );
$out->addModules( array( 'mediawiki.action.view.metadata' ) );
}
@@ -237,16 +237,17 @@ class ImagePage extends Article {
*/
protected function showTOC( $metadata ) {
$r = array(
- '<li><a href="#file">' . wfMessage( 'file-anchor-link' )->escaped() . '</a></li>',
- '<li><a href="#filehistory">' . wfMessage( 'filehist' )->escaped() . '</a></li>',
- '<li><a href="#filelinks">' . wfMessage( 'imagelinks' )->escaped() . '</a></li>',
+ '<li><a href="#file">' . $this->getContext()->msg( 'file-anchor-link' )->escaped() . '</a></li>',
+ '<li><a href="#filehistory">' . $this->getContext()->msg( 'filehist' )->escaped() . '</a></li>',
+ '<li><a href="#filelinks">' . $this->getContext()->msg( 'imagelinks' )->escaped() . '</a></li>',
);
+
+ Hooks::run( 'ImagePageShowTOC', array( $this, &$r ) );
+
if ( $metadata ) {
- $r[] = '<li><a href="#metadata">' . wfMessage( 'metadata' )->escaped() . '</a></li>';
+ $r[] = '<li><a href="#metadata">' . $this->getContext()->msg( 'metadata' )->escaped() . '</a></li>';
}
- wfRunHooks( 'ImagePageShowTOC', array( $this, &$r ) );
-
return '<ul id="filetoc">' . implode( "\n", $r ) . '</ul>';
}
@@ -260,7 +261,7 @@ class ImagePage extends Article {
*/
protected function makeMetadataTable( $metadata ) {
$r = "<div class=\"mw-imagepage-section-metadata\">";
- $r .= wfMessage( 'metadata-help' )->plain();
+ $r .= $this->getContext()->msg( 'metadata-help' )->plain();
$r .= "<table id=\"mw_metadata\" class=\"mw_metadata\">\n";
foreach ( $metadata as $type => $stuff ) {
foreach ( $stuff as $v ) {
@@ -336,19 +337,19 @@ class ImagePage extends Article {
$filename = wfEscapeWikiText( $this->displayImg->getName() );
$linktext = $filename;
- wfRunHooks( 'ImageOpenShowImageInlineBefore', array( &$this, &$out ) );
+ Hooks::run( 'ImageOpenShowImageInlineBefore', array( &$this, &$out ) );
if ( $this->displayImg->allowInlineDisplay() ) {
# image
# "Download high res version" link below the image
- # $msgsize = wfMessage( 'file-info-size', $width_orig, $height_orig,
+ # $msgsize = $this->getContext()->msg( 'file-info-size', $width_orig, $height_orig,
# Linker::formatSize( $this->displayImg->getSize() ), $mime )->escaped();
# We'll show a thumbnail of this image
if ( $width > $maxWidth || $height > $maxHeight || $this->displayImg->isVectorized() ) {
list( $width, $height ) = $this->getDisplayWidthHeight(
$maxWidth, $maxHeight, $width, $height
);
- $linktext = wfMessage( 'show-big-image' )->escaped();
+ $linktext = $this->getContext()->msg( 'show-big-image' )->escaped();
$thumbSizes = $this->getThumbSizes( $width, $height, $width_orig, $height_orig );
# Generate thumbnails or thumbnail links as needed...
@@ -377,14 +378,14 @@ class ImagePage extends Article {
$msgsmall = '';
$sizeLinkBigImagePreview = $this->makeSizeLink( $params, $width, $height );
if ( $sizeLinkBigImagePreview ) {
- $msgsmall .= wfMessage( 'show-big-image-preview' )->
+ $msgsmall .= $this->getContext()->msg( 'show-big-image-preview' )->
rawParams( $sizeLinkBigImagePreview )->
parse();
}
if ( count( $otherSizes ) ) {
$msgsmall .= ' ' .
Html::rawElement( 'span', array( 'class' => 'mw-filepage-other-resolutions' ),
- wfMessage( 'show-big-image-other' )->rawParams( $lang->pipeList( $otherSizes ) )->
+ $this->getContext()->msg( 'show-big-image-other' )->rawParams( $lang->pipeList( $otherSizes ) )->
params( count( $otherSizes ) )->parse()
);
}
@@ -394,7 +395,7 @@ class ImagePage extends Article {
$msgsmall = '';
} else {
# Image is small enough to show full size on image page
- $msgsmall = wfMessage( 'file-nohires' )->parse();
+ $msgsmall = $this->getContext()->msg( 'file-nohires' )->parse();
}
$params['width'] = $width;
@@ -428,7 +429,7 @@ class ImagePage extends Article {
$count = $this->displayImg->pageCount();
if ( $page > 1 ) {
- $label = $out->parse( wfMessage( 'imgmultipageprev' )->text(), false );
+ $label = $out->parse( $this->getContext()->msg( 'imgmultipageprev' )->text(), false );
// on the client side, this link is generated in ajaxifyPageNavigation()
// in the mediawiki.page.image.pagination module
$link = Linker::linkKnown(
@@ -450,7 +451,7 @@ class ImagePage extends Article {
}
if ( $page < $count ) {
- $label = wfMessage( 'imgmultipagenext' )->text();
+ $label = $this->getContext()->msg( 'imgmultipagenext' )->text();
$link = Linker::linkKnown(
$this->getTitle(),
$label,
@@ -487,8 +488,8 @@ class ImagePage extends Article {
'</td><td><div class="multipageimagenavbox">' .
Xml::openElement( 'form', $formParams ) .
Html::hidden( 'title', $this->getTitle()->getPrefixedDBkey() ) .
- wfMessage( 'imgmultigoto' )->rawParams( $select )->parse() .
- Xml::submitButton( wfMessage( 'imgmultigo' )->text() ) .
+ $this->getContext()->msg( 'imgmultigoto' )->rawParams( $select )->parse() .
+ Xml::submitButton( $this->getContext()->msg( 'imgmultigo' )->text() ) .
Xml::closeElement( 'form' ) .
"<hr />$thumb1\n$thumb2<br style=\"clear: both\" /></div></td></tr></table>"
);
@@ -502,12 +503,28 @@ class ImagePage extends Article {
"</div>\n" );
}
- $longDesc = wfMessage( 'parentheses', $this->displayImg->getLongDesc() )->text();
+ $longDesc = $this->getContext()->msg( 'parentheses', $this->displayImg->getLongDesc() )->text();
+
+ $handler = $this->displayImg->getHandler();
+
+ // If this is a filetype with potential issues, warn the user.
+ if ( $handler ) {
+ $warningConfig = $handler->getWarningConfig( $this->displayImg );
+
+ if ( $warningConfig !== null ) {
+ // The warning will be displayed via CSS and JavaScript.
+ // We just need to tell the client side what message to use.
+ $output = $this->getContext()->getOutput();
+ $output->addJsConfigVars( 'wgFileWarning', $warningConfig );
+ $output->addModules( $warningConfig['module'] );
+ $output->addModules( 'mediawiki.filewarning' );
+ }
+ }
$medialink = "[[Media:$filename|$linktext]]";
if ( !$this->displayImg->isSafeFile() ) {
- $warning = wfMessage( 'mediawarning' )->plain();
+ $warning = $this->getContext()->msg( 'mediawarning' )->plain();
// dirmark is needed here to separate the file name, which
// most likely ends in Latin characters, from the description,
// which may begin with the file type. In RTL environment
@@ -619,7 +636,7 @@ EOT
return Html::rawElement( 'a', array(
'href' => $thumbnail->getUrl(),
'class' => 'mw-thumbnail-link'
- ), wfMessage( 'show-big-image-size' )->numParams(
+ ), $this->getContext()->msg( 'show-big-image-size' )->numParams(
$thumbnail->getWidth(), $thumbnail->getHeight()
)->parse() );
} else {
@@ -645,9 +662,9 @@ EOT
$wrap = "<div class=\"sharedUploadNotice\">\n$1\n</div>\n";
$repo = $this->mPage->getFile()->getRepo()->getDisplayName();
- if ( $descUrl && $descText && wfMessage( 'sharedupload-desc-here' )->plain() !== '-' ) {
+ if ( $descUrl && $descText && $this->getContext()->msg( 'sharedupload-desc-here' )->plain() !== '-' ) {
$out->wrapWikiMsg( $wrap, array( 'sharedupload-desc-here', $repo, $descUrl ) );
- } elseif ( $descUrl && wfMessage( 'sharedupload-desc-there' )->plain() !== '-' ) {
+ } elseif ( $descUrl && $this->getContext()->msg( 'sharedupload-desc-there' )->plain() !== '-' ) {
$out->wrapWikiMsg( $wrap, array( 'sharedupload-desc-there', $repo, $descUrl ) );
} else {
$out->wrapWikiMsg( $wrap, array( 'sharedupload', $repo ), ''/*BACKCOMPAT*/ );
@@ -694,7 +711,7 @@ EOT
) {
$ulink = Linker::makeExternalLink(
$this->getUploadUrl(),
- wfMessage( 'uploadnewversion-linktext' )->text()
+ $this->getContext()->msg( 'uploadnewversion-linktext' )->text()
);
$out->addHTML( "<li id=\"mw-imagepage-reupload-link\">"
. "<div class=\"plainlinks\">{$ulink}</div></li>\n" );
@@ -832,7 +849,7 @@ EOT
$liContents = $link;
} elseif ( count( $redirects[$element->page_title] ) === 0 ) {
# Redirect without usages
- $liContents = wfMessage( 'linkstoimage-redirect' )->rawParams( $link, '' )->parse();
+ $liContents = $this->getContext()->msg( 'linkstoimage-redirect' )->rawParams( $link, '' )->parse();
} else {
# Redirect with usages
$li = '';
@@ -855,7 +872,7 @@ EOT
array( 'class' => 'mw-imagepage-redirectstofile' ),
$li
) . "\n";
- $liContents = wfMessage( 'linkstoimage-redirect' )->rawParams(
+ $liContents = $this->getContext()->msg( 'linkstoimage-redirect' )->rawParams(
$link, $ul )->parse();
}
$out->addHTML( Html::rawElement(
@@ -901,7 +918,7 @@ EOT
} else {
$link = Linker::makeExternalLink( $file->getDescriptionUrl(),
$file->getTitle()->getPrefixedText() );
- $fromSrc = wfMessage( 'shared-repo-from', $file->getRepo()->getDisplayName() )->text();
+ $fromSrc = $this->getContext()->msg( 'shared-repo-from', $file->getRepo()->getDisplayName() )->text();
}
$out->addHTML( "<li>{$link} {$fromSrc}</li>\n" );
}
@@ -930,7 +947,7 @@ EOT
*/
function showError( $description ) {
$out = $this->getContext()->getOutput();
- $out->setPageTitle( wfMessage( 'internalerror' ) );
+ $out->setPageTitle( $this->getContext()->msg( 'internalerror' ) );
$out->setRobotPolicy( 'noindex,nofollow' );
$out->setArticleRelated( false );
$out->enableClientCache( false );
@@ -1008,7 +1025,7 @@ EOT
$code = wfBCP47( $lang );
$name = Language::fetchLanguageName( $code, $this->getContext()->getLanguage()->getCode() );
if ( $name !== '' ) {
- $display = wfMessage( 'img-lang-opt', $code, $name )->text();
+ $display = $this->getContext()->msg( 'img-lang-opt', $code, $name )->text();
} else {
$display = $code;
}
@@ -1024,7 +1041,7 @@ EOT
// Its hard to know if the content is really in the default language, or
// if its just unmarked content that could be in any language.
$opts = Xml::option(
- wfMessage( 'img-lang-default' )->text(),
+ $this->getContext()->msg( 'img-lang-default' )->text(),
$defaultLang,
$defaultLang === $curLang
) . $opts;
@@ -1032,7 +1049,7 @@ EOT
if ( !$haveCurrentLang && $defaultLang !== $curLang ) {
$name = Language::fetchLanguageName( $curLang, $this->getContext()->getLanguage()->getCode() );
if ( $name !== '' ) {
- $display = wfMessage( 'img-lang-opt', $curLang, $name )->text();
+ $display = $this->getContext()->msg( 'img-lang-opt', $curLang, $name )->text();
} else {
$display = $curLang;
}
@@ -1044,9 +1061,9 @@ EOT
array( 'id' => 'mw-imglangselector', 'name' => 'lang' ),
$opts
);
- $submit = Xml::submitButton( wfMessage( 'img-lang-go' )->text() );
+ $submit = Xml::submitButton( $this->getContext()->msg( 'img-lang-go' )->text() );
- $formContents = wfMessage( 'img-lang-info' )->rawParams( $select, $submit )->parse()
+ $formContents = $this->getContext()->msg( 'img-lang-info' )->rawParams( $select, $submit )->parse()
. Html::hidden( 'title', $this->getTitle()->getPrefixedDBkey() );
$langSelectLine = Html::rawElement( 'div', array( 'id' => 'mw-imglangselector-line' ),
@@ -1199,9 +1216,9 @@ class ImageHistoryList extends ContextSource {
. $this->msg( 'filehist-help' )->parseAsBlock()
. $navLinks . "\n"
. Xml::openElement( 'table', array( 'class' => 'wikitable filehistory' ) ) . "\n"
- . '<tr><td></td>'
+ . '<tr><th></th>'
. ( $this->current->isLocal()
- && ( $this->getUser()->isAllowedAny( 'delete', 'deletedhistory' ) ) ? '<td></td>' : '' )
+ && ( $this->getUser()->isAllowedAny( 'delete', 'deletedhistory' ) ) ? '<th></th>' : '' )
. '<th>' . $this->msg( 'filehist-datetime' )->escaped() . '</th>'
. ( $this->showThumb ? '<th>' . $this->msg( 'filehist-thumb' )->escaped() . '</th>' : '' )
. '<th>' . $this->msg( 'filehist-dimensions' )->escaped() . '</th>'
@@ -1364,7 +1381,6 @@ class ImageHistoryList extends ContextSource {
} else {
if ( $local ) {
$row .= Linker::userLink( $userId, $userText );
- $row .= $this->msg( 'word-separator' )->escaped();
$row .= '<span style="white-space: nowrap;">';
$row .= Linker::userToolLinks( $userId, $userText );
$row .= '</span>';
@@ -1384,7 +1400,7 @@ class ImageHistoryList extends ContextSource {
}
$rowClass = null;
- wfRunHooks( 'ImagePageFileHistoryLine', array( $this, $file, &$row, &$rowClass ) );
+ Hooks::run( 'ImagePageFileHistoryLine', array( $this, $file, &$row, &$rowClass ) );
$classAttr = $rowClass ? " class='$rowClass'" : '';
return "<tr{$classAttr}>{$row}</tr>\n";
diff --git a/includes/page/WikiPage.php b/includes/page/WikiPage.php
index 9ade16e5..7c789249 100644
--- a/includes/page/WikiPage.php
+++ b/includes/page/WikiPage.php
@@ -31,8 +31,6 @@ interface Page {
*
* Some fields are public only for backwards-compatibility. Use accessors.
* In the past, this class was part of Article.php and everything was public.
- *
- * @internal documentation reviewed 15 Mar 2010
*/
class WikiPage implements Page, IDBAccessObject {
// Constants for $mDataLoadedFrom and related
@@ -50,7 +48,7 @@ class WikiPage implements Page, IDBAccessObject {
public $mLatest = false; // !< Integer (false means "not loaded")
/**@}}*/
- /** @var stdclass Map of cache fields (text, parser output, ect) for a proposed/new edit */
+ /** @var stdClass Map of cache fields (text, parser output, ect) for a proposed/new edit */
public $mPreparedEdit = false;
/**
@@ -89,11 +87,6 @@ class WikiPage implements Page, IDBAccessObject {
protected $mLinksUpdated = '19700101000000';
/**
- * @var int|null
- */
- protected $mCounter = null;
-
- /**
* Constructor and clear the article
* @param Title $title Reference to a Title object.
*/
@@ -247,7 +240,6 @@ class WikiPage implements Page, IDBAccessObject {
*/
protected function clearCacheFields() {
$this->mId = null;
- $this->mCounter = null;
$this->mRedirectTarget = null; // Title object if set
$this->mLastRevision = null; // Latest revision
$this->mTouched = '19700101000000';
@@ -284,7 +276,6 @@ class WikiPage implements Page, IDBAccessObject {
'page_namespace',
'page_title',
'page_restrictions',
- 'page_counter',
'page_is_redirect',
'page_is_new',
'page_random',
@@ -315,11 +306,11 @@ class WikiPage implements Page, IDBAccessObject {
protected function pageData( $dbr, $conditions, $options = array() ) {
$fields = self::selectFields();
- wfRunHooks( 'ArticlePageDataBefore', array( &$this, &$fields ) );
+ Hooks::run( 'ArticlePageDataBefore', array( &$this, &$fields ) );
$row = $dbr->selectRow( 'page', $fields, $conditions, __METHOD__, $options );
- wfRunHooks( 'ArticlePageDataAfter', array( &$this, &$row ) );
+ Hooks::run( 'ArticlePageDataAfter', array( &$this, &$row ) );
return $row;
}
@@ -352,8 +343,7 @@ class WikiPage implements Page, IDBAccessObject {
}
/**
- * Set the general counter, title etc data loaded from
- * some source.
+ * Load the object from a given source by title
*
* @param object|string|int $from One of the following:
* - A DB query result object.
@@ -377,14 +367,12 @@ class WikiPage implements Page, IDBAccessObject {
$data = $this->pageDataFromTitle( wfGetDB( DB_MASTER ), $this->mTitle );
} elseif ( $from === self::READ_NORMAL ) {
$data = $this->pageDataFromTitle( wfGetDB( DB_SLAVE ), $this->mTitle );
- // Use a "last rev inserted" timestamp key to diminish the issue of slave lag.
- // Note that DB also stores the master position in the session and checks it.
- $touched = $this->getCachedLastEditTime();
- if ( $touched ) { // key set
- if ( !$data || $touched > wfTimestamp( TS_MW, $data->page_touched ) ) {
- $from = self::READ_LATEST;
- $data = $this->pageDataFromTitle( wfGetDB( DB_MASTER ), $this->mTitle );
- }
+ if ( !$data
+ && wfGetLB()->getServerCount() > 1
+ && wfGetLB()->hasOrMadeRecentMasterChanges()
+ ) {
+ $from = self::READ_LATEST;
+ $data = $this->pageDataFromTitle( wfGetDB( DB_MASTER ), $this->mTitle );
}
} else {
// No idea from where the caller got this data, assume slave database.
@@ -403,7 +391,7 @@ class WikiPage implements Page, IDBAccessObject {
* @param string|int $from One of the following:
* - "fromdb" or WikiPage::READ_NORMAL if the data comes from a slave DB
* - "fromdbmaster" or WikiPage::READ_LATEST if the data comes from the master DB
- * - "forupdate" or WikiPage::READ_LOCKING if the data comes from from
+ * - "forupdate" or WikiPage::READ_LOCKING if the data comes from
* the master DB using SELECT FOR UPDATE
*/
public function loadFromRow( $data, $from ) {
@@ -419,7 +407,6 @@ class WikiPage implements Page, IDBAccessObject {
$this->mTitle->loadRestrictions( $data->page_restrictions );
$this->mId = intval( $data->page_id );
- $this->mCounter = intval( $data->page_counter );
$this->mTouched = wfTimestamp( TS_MW, $data->page_touched );
$this->mLinksUpdated = wfTimestampOrNull( TS_MW, $data->page_links_updated );
$this->mIsRedirect = intval( $data->page_is_redirect );
@@ -477,17 +464,6 @@ class WikiPage implements Page, IDBAccessObject {
}
/**
- * @return int The view count for the page
- */
- public function getCount() {
- if ( !$this->mDataLoaded ) {
- $this->loadPageData();
- }
-
- return $this->mCounter;
- }
-
- /**
* Tests if the article content represents a redirect
*
* @return bool
@@ -577,7 +553,6 @@ class WikiPage implements Page, IDBAccessObject {
* @return Revision|null
*/
public function getOldestRevision() {
- wfProfileIn( __METHOD__ );
// Try using the slave database first, then try the master
$continue = 2;
@@ -608,7 +583,6 @@ class WikiPage implements Page, IDBAccessObject {
}
}
- wfProfileOut( __METHOD__ );
return $row ? Revision::newFromRow( $row ) : null;
}
@@ -626,13 +600,23 @@ class WikiPage implements Page, IDBAccessObject {
return; // page doesn't exist or is missing page_latest info
}
- // Bug 37225: if session S1 loads the page row FOR UPDATE, the result always includes the
- // latest changes committed. This is true even within REPEATABLE-READ transactions, where
- // S1 normally only sees changes committed before the first S1 SELECT. Thus we need S1 to
- // also gets the revision row FOR UPDATE; otherwise, it may not find it since a page row
- // UPDATE and revision row INSERT by S2 may have happened after the first S1 SELECT.
- // http://dev.mysql.com/doc/refman/5.0/en/set-transaction.html#isolevel_repeatable-read.
- $flags = ( $this->mDataLoadedFrom == self::READ_LOCKING ) ? Revision::READ_LOCKING : 0;
+ if ( $this->mDataLoadedFrom == self::READ_LOCKING ) {
+ // Bug 37225: if session S1 loads the page row FOR UPDATE, the result always
+ // includes the latest changes committed. This is true even within REPEATABLE-READ
+ // transactions, where S1 normally only sees changes committed before the first S1
+ // SELECT. Thus we need S1 to also gets the revision row FOR UPDATE; otherwise, it
+ // may not find it since a page row UPDATE and revision row INSERT by S2 may have
+ // happened after the first S1 SELECT.
+ // http://dev.mysql.com/doc/refman/5.0/en/set-transaction.html#isolevel_repeatable-read.
+ $flags = Revision::READ_LOCKING;
+ } elseif ( $this->mDataLoadedFrom == self::READ_LATEST ) {
+ // Bug T93976: if page_latest was loaded from the master, fetch the
+ // revision from there as well, as it may not exist yet on a slave DB.
+ // Also, this keeps the queries in the same REPEATABLE-READ snapshot.
+ $flags = Revision::READ_LATEST;
+ } else {
+ $flags = 0;
+ }
$revision = Revision::newFromPageId( $this->getId(), $latest, $flags );
if ( $revision ) { // sanity
$this->setLastEdit( $revision );
@@ -825,29 +809,6 @@ class WikiPage implements Page, IDBAccessObject {
}
/**
- * Get the cached timestamp for the last time the page changed.
- * This is only used to help handle slave lag by comparing to page_touched.
- * @return string MW timestamp
- */
- protected function getCachedLastEditTime() {
- global $wgMemc;
- $key = wfMemcKey( 'page-lastedit', md5( $this->mTitle->getPrefixedDBkey() ) );
- return $wgMemc->get( $key );
- }
-
- /**
- * Set the cached timestamp for the last time the page changed.
- * This is only used to help handle slave lag by comparing to page_touched.
- * @param string $timestamp
- * @return void
- */
- public function setCachedLastEditTime( $timestamp ) {
- global $wgMemc;
- $key = wfMemcKey( 'page-lastedit', md5( $this->mTitle->getPrefixedDBkey() ) );
- $wgMemc->set( $key, wfTimestamp( TS_MW, $timestamp ), 60 * 15 );
- }
-
- /**
* Determine whether a page would be suitable for being counted as an
* article in the site_stats table based on the title & its content
*
@@ -995,7 +956,7 @@ class WikiPage implements Page, IDBAccessObject {
$source = $this->mTitle->getFullURL( 'redirect=no' );
return $rt->getFullURL( array( 'rdfrom' => $source ) );
} else {
- // External pages pages without "local" bit set are not valid
+ // External pages without "local" bit set are not valid
// redirect targets
return false;
}
@@ -1075,7 +1036,6 @@ class WikiPage implements Page, IDBAccessObject {
* @return array Array of authors, duplicates not removed
*/
public function getLastNAuthors( $num, $revLatest = 0 ) {
- wfProfileIn( __METHOD__ );
// First try the slave
// If that doesn't have the latest revision, try the master
$continue = 2;
@@ -1096,7 +1056,6 @@ class WikiPage implements Page, IDBAccessObject {
);
if ( !$res ) {
- wfProfileOut( __METHOD__ );
return array();
}
@@ -1116,7 +1075,6 @@ class WikiPage implements Page, IDBAccessObject {
$authors[] = $row->rev_user_text;
}
- wfProfileOut( __METHOD__ );
return $authors;
}
@@ -1149,7 +1107,6 @@ class WikiPage implements Page, IDBAccessObject {
* @return ParserOutput|bool ParserOutput or false if the revision was not found
*/
public function getParserOutput( ParserOptions $parserOptions, $oldid = null ) {
- wfProfileIn( __METHOD__ );
$useParserCache = $this->isParserCacheUsed( $parserOptions, $oldid );
wfDebug( __METHOD__ . ': using parser cache: ' . ( $useParserCache ? 'yes' : 'no' ) . "\n" );
@@ -1160,7 +1117,6 @@ class WikiPage implements Page, IDBAccessObject {
if ( $useParserCache ) {
$parserOutput = ParserCache::singleton()->get( $this, $parserOptions );
if ( $parserOutput !== false ) {
- wfProfileOut( __METHOD__ );
return $parserOutput;
}
}
@@ -1172,8 +1128,6 @@ class WikiPage implements Page, IDBAccessObject {
$pool = new PoolWorkArticleView( $this, $parserOptions, $oldid, $useParserCache );
$pool->execute();
- wfProfileOut( __METHOD__ );
-
return $pool->getParserOutput();
}
@@ -1183,17 +1137,11 @@ class WikiPage implements Page, IDBAccessObject {
* @param int $oldid The revision id being viewed. If not given or 0, latest revision is assumed.
*/
public function doViewUpdates( User $user, $oldid = 0 ) {
- global $wgDisableCounters;
if ( wfReadOnly() ) {
return;
}
- // Don't update page view counters on views from bot users (bug 14044)
- if ( !$wgDisableCounters && !$user->isAllowed( 'bot' ) && $this->exists() ) {
- DeferredUpdates::addUpdate( new ViewCountUpdate( $this->getId() ) );
- DeferredUpdates::addUpdate( new SiteStatsUpdate( 1, 0, 0 ) );
- }
-
+ Hooks::run( 'PageViewUpdates', array( $this, $user ) );
// Update newtalk / watchlist notification status
$user->clearNotification( $this->mTitle, $oldid );
}
@@ -1205,7 +1153,7 @@ class WikiPage implements Page, IDBAccessObject {
public function doPurge() {
global $wgUseSquid;
- if ( !wfRunHooks( 'ArticlePurge', array( &$this ) ) ) {
+ if ( !Hooks::run( 'ArticlePurge', array( &$this ) ) ) {
return false;
}
@@ -1255,14 +1203,12 @@ class WikiPage implements Page, IDBAccessObject {
* @return int The newly created page_id key, or false if the title already existed
*/
public function insertOn( $dbw ) {
- wfProfileIn( __METHOD__ );
$page_id = $dbw->nextSequenceValue( 'page_page_id_seq' );
$dbw->insert( 'page', array(
'page_id' => $page_id,
'page_namespace' => $this->mTitle->getNamespace(),
'page_title' => $this->mTitle->getDBkey(),
- 'page_counter' => 0,
'page_restrictions' => '',
'page_is_redirect' => 0, // Will set this shortly...
'page_is_new' => 1,
@@ -1279,7 +1225,6 @@ class WikiPage implements Page, IDBAccessObject {
$this->mId = $newid;
$this->mTitle->resetArticleID( $newid );
}
- wfProfileOut( __METHOD__ );
return $affected ? $newid : false;
}
@@ -1302,7 +1247,12 @@ class WikiPage implements Page, IDBAccessObject {
) {
global $wgContentHandlerUseDB;
- wfProfileIn( __METHOD__ );
+ // Assertion to try to catch T92046
+ if ( (int)$revision->getId() === 0 ) {
+ throw new InvalidArgumentException(
+ __METHOD__ . ': Revision has ID ' . var_export( $revision->getId(), 1 )
+ );
+ }
$content = $revision->getContent();
$len = $content ? $content->getSize() : 0;
@@ -1337,7 +1287,6 @@ class WikiPage implements Page, IDBAccessObject {
if ( $result ) {
$this->updateRedirectOn( $dbw, $rt, $lastRevIsRedirect );
$this->setLastEdit( $revision );
- $this->setCachedLastEditTime( $now );
$this->mLatest = $revision->getId();
$this->mIsRedirect = (bool)$rt;
// Update the LinkCache.
@@ -1345,7 +1294,6 @@ class WikiPage implements Page, IDBAccessObject {
$this->mLatest, $revision->getContentModel() );
}
- wfProfileOut( __METHOD__ );
return $result;
}
@@ -1370,7 +1318,6 @@ class WikiPage implements Page, IDBAccessObject {
return true;
}
- wfProfileIn( __METHOD__ );
if ( $isRedirect ) {
$this->insertRedirectEntry( $redirectTitle );
} else {
@@ -1382,7 +1329,6 @@ class WikiPage implements Page, IDBAccessObject {
if ( $this->getTitle()->getNamespace() == NS_FILE ) {
RepoGroup::singleton()->getLocalRepo()->invalidateImageRedirect( $this->getTitle() );
}
- wfProfileOut( __METHOD__ );
return ( $dbw->affectedRows() != 0 );
}
@@ -1398,7 +1344,6 @@ class WikiPage implements Page, IDBAccessObject {
* @return bool
*/
public function updateIfNewerOn( $dbw, $revision ) {
- wfProfileIn( __METHOD__ );
$row = $dbw->selectRow(
array( 'revision', 'page' ),
@@ -1410,7 +1355,6 @@ class WikiPage implements Page, IDBAccessObject {
if ( $row ) {
if ( wfTimestamp( TS_MW, $row->rev_timestamp ) >= $revision->getTimestamp() ) {
- wfProfileOut( __METHOD__ );
return false;
}
$prev = $row->rev_id;
@@ -1423,7 +1367,6 @@ class WikiPage implements Page, IDBAccessObject {
$ret = $this->updateRevisionOn( $dbw, $revision, $prev, $lastRevIsRedirect );
- wfProfileOut( __METHOD__ );
return $ret;
}
@@ -1542,18 +1485,26 @@ class WikiPage implements Page, IDBAccessObject {
*/
public function replaceSectionContent( $sectionId, Content $sectionContent, $sectionTitle = '',
$edittime = null ) {
- wfProfileIn( __METHOD__ );
$baseRevId = null;
if ( $edittime && $sectionId !== 'new' ) {
- $dbw = wfGetDB( DB_MASTER );
- $rev = Revision::loadFromTimestamp( $dbw, $this->mTitle, $edittime );
+ $dbr = wfGetDB( DB_SLAVE );
+ $rev = Revision::loadFromTimestamp( $dbr, $this->mTitle, $edittime );
+ // Try the master if this thread may have just added it.
+ // This could be abstracted into a Revision method, but we don't want
+ // to encourage loading of revisions by timestamp.
+ if ( !$rev
+ && wfGetLB()->getServerCount() > 1
+ && wfGetLB()->hasOrMadeRecentMasterChanges()
+ ) {
+ $dbw = wfGetDB( DB_MASTER );
+ $rev = Revision::loadFromTimestamp( $dbw, $this->mTitle, $edittime );
+ }
if ( $rev ) {
$baseRevId = $rev->getId();
}
}
- wfProfileOut( __METHOD__ );
return $this->replaceSectionAtRev( $sectionId, $sectionContent, $sectionTitle, $baseRevId );
}
@@ -1573,14 +1524,12 @@ class WikiPage implements Page, IDBAccessObject {
public function replaceSectionAtRev( $sectionId, Content $sectionContent,
$sectionTitle = '', $baseRevId = null
) {
- wfProfileIn( __METHOD__ );
if ( strval( $sectionId ) === '' ) {
// Whole-page edit; let the whole text through
$newContent = $sectionContent;
} else {
if ( !$this->supportsSections() ) {
- wfProfileOut( __METHOD__ );
throw new MWException( "sections not supported for content model " .
$this->getContentHandler()->getModelID() );
}
@@ -1589,14 +1538,10 @@ class WikiPage implements Page, IDBAccessObject {
if ( is_null( $baseRevId ) || $sectionId === 'new' ) {
$oldContent = $this->getContent();
} else {
- // TODO: try DB_SLAVE first
- $dbw = wfGetDB( DB_MASTER );
- $rev = Revision::loadFromId( $dbw, $baseRevId );
-
+ $rev = Revision::newFromId( $baseRevId );
if ( !$rev ) {
wfDebug( __METHOD__ . " asked for bogus section (page: " .
$this->getId() . "; section: $sectionId)\n" );
- wfProfileOut( __METHOD__ );
return null;
}
@@ -1605,14 +1550,12 @@ class WikiPage implements Page, IDBAccessObject {
if ( !$oldContent ) {
wfDebug( __METHOD__ . ": no page text\n" );
- wfProfileOut( __METHOD__ );
return null;
}
$newContent = $oldContent->replaceSection( $sectionId, $sectionContent, $sectionTitle );
}
- wfProfileOut( __METHOD__ );
return $newContent;
}
@@ -1662,7 +1605,9 @@ class WikiPage implements Page, IDBAccessObject {
* error will be returned. These two conditions are also possible with
* auto-detection due to MediaWiki's performance-optimised locking strategy.
*
- * @param bool|int $baseRevId The revision ID this edit was based off, if any
+ * @param bool|int $baseRevId The revision ID this edit was based off, if any.
+ * This is not the parent revision ID, rather the revision ID for older
+ * content used as the source for a rollback, for example.
* @param User $user The user doing the edit
*
* @throws MWException
@@ -1722,9 +1667,11 @@ class WikiPage implements Page, IDBAccessObject {
* error will be returned. These two conditions are also possible with
* auto-detection due to MediaWiki's performance-optimised locking strategy.
*
- * @param bool|int $baseRevId The revision ID this edit was based off, if any
+ * @param bool|int $baseRevId The revision ID this edit was based off, if any.
+ * This is not the parent revision ID, rather the revision ID for older
+ * content used as the source for a rollback, for example.
* @param User $user The user doing the edit
- * @param string $serialisation_format Format for storing the content in the
+ * @param string $serialFormat Format for storing the content in the
* database.
*
* @throws MWException
@@ -1745,7 +1692,7 @@ class WikiPage implements Page, IDBAccessObject {
* @since 1.21
*/
public function doEditContent( Content $content, $summary, $flags = 0, $baseRevId = false,
- User $user = null, $serialisation_format = null
+ User $user = null, $serialFormat = null
) {
global $wgUser, $wgUseAutomaticEditSummaries, $wgUseRCPatrol, $wgUseNPPatrol;
@@ -1754,10 +1701,7 @@ class WikiPage implements Page, IDBAccessObject {
throw new MWException( 'Something is trying to edit an article with an empty title' );
}
- wfProfileIn( __METHOD__ );
-
if ( !$content->getContentHandler()->canBeUsedOn( $this->getTitle() ) ) {
- wfProfileOut( __METHOD__ );
return Status::newFatal( 'content-not-allowed-here',
ContentHandler::getLocalizedName( $content->getModel() ),
$this->getTitle()->getPrefixedText() );
@@ -1777,7 +1721,7 @@ class WikiPage implements Page, IDBAccessObject {
$hook_args = array( &$this, &$user, &$content, &$summary,
$flags & EDIT_MINOR, null, null, &$flags, &$status );
- if ( !wfRunHooks( 'PageContentSave', $hook_args )
+ if ( !Hooks::run( 'PageContentSave', $hook_args )
|| !ContentHandler::runLegacyHooks( 'ArticleSave', $hook_args ) ) {
wfDebug( __METHOD__ . ": ArticleSave or ArticleSaveContent hook aborted save!\n" );
@@ -1786,7 +1730,6 @@ class WikiPage implements Page, IDBAccessObject {
$status->fatal( 'edit-hook-aborted' );
}
- wfProfileOut( __METHOD__ );
return $status;
}
@@ -1811,7 +1754,7 @@ class WikiPage implements Page, IDBAccessObject {
$summary = $handler->getAutosummary( $old_content, $content, $flags );
}
- $editInfo = $this->prepareContentForEdit( $content, null, $user, $serialisation_format );
+ $editInfo = $this->prepareContentForEdit( $content, null, $user, $serialFormat );
$serialized = $editInfo->pst;
/**
@@ -1833,11 +1776,9 @@ class WikiPage implements Page, IDBAccessObject {
wfDebug( __METHOD__ . ": EDIT_UPDATE specified but article doesn't exist\n" );
$status->fatal( 'edit-gone-missing' );
- wfProfileOut( __METHOD__ );
return $status;
} elseif ( !$old_content ) {
// Sanity check for bug 37225
- wfProfileOut( __METHOD__ );
throw new MWException( "Could not find text for current revision {$oldid}." );
}
@@ -1853,27 +1794,21 @@ class WikiPage implements Page, IDBAccessObject {
'user_text' => $user->getName(),
'timestamp' => $now,
'content_model' => $content->getModel(),
- 'content_format' => $serialisation_format,
+ 'content_format' => $serialFormat,
) ); // XXX: pass content object?!
$changed = !$content->equals( $old_content );
if ( $changed ) {
- if ( !$content->isValid() ) {
- wfProfileOut( __METHOD__ );
- throw new MWException( "New content failed validity check!" );
- }
-
$dbw->begin( __METHOD__ );
try {
- $prepStatus = $content->prepareSave( $this, $flags, $baseRevId, $user );
+ $prepStatus = $content->prepareSave( $this, $flags, $oldid, $user );
$status->merge( $prepStatus );
if ( !$status->isOK() ) {
$dbw->rollback( __METHOD__ );
- wfProfileOut( __METHOD__ );
return $status;
}
$revisionId = $revision->insertOn( $dbw );
@@ -1889,11 +1824,10 @@ class WikiPage implements Page, IDBAccessObject {
$dbw->rollback( __METHOD__ );
- wfProfileOut( __METHOD__ );
return $status;
}
- wfRunHooks( 'NewRevisionFromEditComplete', array( $this, $revision, $baseRevId, $user ) );
+ Hooks::run( 'NewRevisionFromEditComplete', array( $this, $revision, $baseRevId, $user ) );
// Update recentchanges
if ( !( $flags & EDIT_SUPPRESS_RC ) ) {
// Mark as patrolled if the user can do so
@@ -1911,7 +1845,7 @@ class WikiPage implements Page, IDBAccessObject {
}
}
$user->incEditCount();
- } catch ( MWException $e ) {
+ } catch ( Exception $e ) {
$dbw->rollback( __METHOD__ );
// Question: Would it perhaps be better if this method turned all
// exceptions into $status's?
@@ -1948,13 +1882,12 @@ class WikiPage implements Page, IDBAccessObject {
$dbw->begin( __METHOD__ );
try {
- $prepStatus = $content->prepareSave( $this, $flags, $baseRevId, $user );
+ $prepStatus = $content->prepareSave( $this, $flags, $oldid, $user );
$status->merge( $prepStatus );
if ( !$status->isOK() ) {
$dbw->rollback( __METHOD__ );
- wfProfileOut( __METHOD__ );
return $status;
}
@@ -1968,7 +1901,6 @@ class WikiPage implements Page, IDBAccessObject {
$dbw->rollback( __METHOD__ );
$status->fatal( 'edit-already-exists' );
- wfProfileOut( __METHOD__ );
return $status;
}
@@ -1984,7 +1916,7 @@ class WikiPage implements Page, IDBAccessObject {
'user_text' => $user->getName(),
'timestamp' => $now,
'content_model' => $content->getModel(),
- 'content_format' => $serialisation_format,
+ 'content_format' => $serialFormat,
) );
$revisionId = $revision->insertOn( $dbw );
@@ -1998,7 +1930,7 @@ class WikiPage implements Page, IDBAccessObject {
// Update the page record with revision data
$this->updateRevisionOn( $dbw, $revision, 0 );
- wfRunHooks( 'NewRevisionFromEditComplete', array( $this, $revision, false, $user ) );
+ Hooks::run( 'NewRevisionFromEditComplete', array( $this, $revision, false, $user ) );
// Update recentchanges
if ( !( $flags & EDIT_SUPPRESS_RC ) ) {
@@ -2016,7 +1948,7 @@ class WikiPage implements Page, IDBAccessObject {
}
$user->incEditCount();
- } catch ( MWException $e ) {
+ } catch ( Exception $e ) {
$dbw->rollback( __METHOD__ );
throw $e;
}
@@ -2029,7 +1961,7 @@ class WikiPage implements Page, IDBAccessObject {
$flags & EDIT_MINOR, null, null, &$flags, $revision );
ContentHandler::runLegacyHooks( 'ArticleInsertComplete', $hook_args );
- wfRunHooks( 'PageContentInsertComplete', $hook_args );
+ Hooks::run( 'PageContentInsertComplete', $hook_args );
}
// Do updates right now unless deferral was requested
@@ -2044,14 +1976,14 @@ class WikiPage implements Page, IDBAccessObject {
$flags & EDIT_MINOR, null, null, &$flags, $revision, &$status, $baseRevId );
ContentHandler::runLegacyHooks( 'ArticleSaveComplete', $hook_args );
- wfRunHooks( 'PageContentSaveComplete', $hook_args );
+ Hooks::run( 'PageContentSaveComplete', $hook_args );
// Promote user to any groups they meet the criteria for
$dbw->onTransactionIdle( function () use ( $user ) {
$user->addAutopromoteOnceGroups( 'onEdit' );
+ $user->addAutopromoteOnceGroups( 'onView' ); // b/c
} );
- wfProfileOut( __METHOD__ );
return $status;
}
@@ -2083,7 +2015,7 @@ class WikiPage implements Page, IDBAccessObject {
/**
* Prepare text which is about to be saved.
- * Returns a stdclass with source, pst and output members
+ * Returns a stdClass with source, pst and output members
*
* @deprecated since 1.21: use prepareContentForEdit instead.
* @return object
@@ -2096,54 +2028,109 @@ class WikiPage implements Page, IDBAccessObject {
/**
* Prepare content which is about to be saved.
- * Returns a stdclass with source, pst and output members
+ * Returns a stdClass with source, pst and output members
*
* @param Content $content
- * @param int|null $revid
+ * @param Revision|int|null $revision Revision object. For backwards compatibility, a
+ * revision ID is also accepted, but this is deprecated.
* @param User|null $user
- * @param string|null $serialization_format
+ * @param string|null $serialFormat
+ * @param bool $useCache Check shared prepared edit cache
*
- * @return bool|object
+ * @return object
*
* @since 1.21
*/
- public function prepareContentForEdit( Content $content, $revid = null, User $user = null,
- $serialization_format = null
+ public function prepareContentForEdit(
+ Content $content, $revision = null, User $user = null, $serialFormat = null, $useCache = true
) {
- global $wgContLang, $wgUser;
+ global $wgContLang, $wgUser, $wgAjaxEditStash;
+
+ if ( is_object( $revision ) ) {
+ $revid = $revision->getId();
+ } else {
+ $revid = $revision;
+ // This code path is deprecated, and nothing is known to
+ // use it, so performance here shouldn't be a worry.
+ if ( $revid !== null ) {
+ $revision = Revision::newFromId( $revid, Revision::READ_LATEST );
+ } else {
+ $revision = null;
+ }
+ }
+
$user = is_null( $user ) ? $wgUser : $user;
//XXX: check $user->getId() here???
- // Use a sane default for $serialization_format, see bug 57026
- if ( $serialization_format === null ) {
- $serialization_format = $content->getContentHandler()->getDefaultFormat();
+ // Use a sane default for $serialFormat, see bug 57026
+ if ( $serialFormat === null ) {
+ $serialFormat = $content->getContentHandler()->getDefaultFormat();
}
if ( $this->mPreparedEdit
&& $this->mPreparedEdit->newContent
&& $this->mPreparedEdit->newContent->equals( $content )
&& $this->mPreparedEdit->revid == $revid
- && $this->mPreparedEdit->format == $serialization_format
+ && $this->mPreparedEdit->format == $serialFormat
// XXX: also check $user here?
) {
// Already prepared
return $this->mPreparedEdit;
}
+ // The edit may have already been prepared via api.php?action=stashedit
+ $cachedEdit = $useCache && $wgAjaxEditStash
+ ? ApiStashEdit::checkCache( $this->getTitle(), $content, $user )
+ : false;
+
$popts = ParserOptions::newFromUserAndLang( $user, $wgContLang );
- wfRunHooks( 'ArticlePrepareTextForEdit', array( $this, $popts ) );
+ Hooks::run( 'ArticlePrepareTextForEdit', array( $this, $popts ) );
$edit = (object)array();
+ if ( $cachedEdit ) {
+ $edit->timestamp = $cachedEdit->timestamp;
+ } else {
+ $edit->timestamp = wfTimestampNow();
+ }
+ // @note: $cachedEdit is not used if the rev ID was referenced in the text
$edit->revid = $revid;
- $edit->timestamp = wfTimestampNow();
- $edit->pstContent = $content ? $content->preSaveTransform( $this->mTitle, $user, $popts ) : null;
+ if ( $cachedEdit ) {
+ $edit->pstContent = $cachedEdit->pstContent;
+ } else {
+ $edit->pstContent = $content
+ ? $content->preSaveTransform( $this->mTitle, $user, $popts )
+ : null;
+ }
- $edit->format = $serialization_format;
+ $edit->format = $serialFormat;
$edit->popts = $this->makeParserOptions( 'canonical' );
- $edit->output = $edit->pstContent
- ? $edit->pstContent->getParserOutput( $this->mTitle, $revid, $edit->popts )
- : null;
+ if ( $cachedEdit ) {
+ $edit->output = $cachedEdit->output;
+ } else {
+ if ( $revision ) {
+ // We get here if vary-revision is set. This means that this page references
+ // itself (such as via self-transclusion). In this case, we need to make sure
+ // that any such self-references refer to the newly-saved revision, and not
+ // to the previous one, which could otherwise happen due to slave lag.
+ $oldCallback = $edit->popts->setCurrentRevisionCallback(
+ function ( $title, $parser = false ) use ( $revision, &$oldCallback ) {
+ if ( $title->equals( $revision->getTitle() ) ) {
+ return $revision;
+ } else {
+ return call_user_func(
+ $oldCallback,
+ $title,
+ $parser
+ );
+ }
+ }
+ );
+ }
+ $edit->output = $edit->pstContent
+ ? $edit->pstContent->getParserOutput( $this->mTitle, $revid, $edit->popts )
+ : null;
+ }
$edit->newContent = $content;
$edit->oldContent = $this->getContent( Revision::RAW );
@@ -2151,7 +2138,7 @@ class WikiPage implements Page, IDBAccessObject {
// NOTE: B/C for hooks! don't use these fields!
$edit->newText = $edit->newContent ? ContentHandler::getContentText( $edit->newContent ) : '';
$edit->oldText = $edit->oldContent ? ContentHandler::getContentText( $edit->oldContent ) : '';
- $edit->pst = $edit->pstContent ? $edit->pstContent->serialize( $serialization_format ) : '';
+ $edit->pst = $edit->pstContent ? $edit->pstContent->serialize( $serialFormat ) : '';
$this->mPreparedEdit = $edit;
return $edit;
@@ -2168,17 +2155,23 @@ class WikiPage implements Page, IDBAccessObject {
* @param array $options Array of options, following indexes are used:
* - changed: boolean, whether the revision changed the content (default true)
* - created: boolean, whether the revision created the page (default false)
- * - oldcountable: boolean or null (default null):
+ * - moved: boolean, whether the page was moved (default false)
+ * - oldcountable: boolean, null, or string 'no-change' (default null):
* - boolean: whether the page was counted as an article before that
* revision, only used in changed is true and created is false
- * - null: don't change the article count
+ * - null: if created is false, don't update the article count; if created
+ * is true, do update the article count
+ * - 'no-change': don't update the article count, ever
*/
public function doEditUpdates( Revision $revision, User $user, array $options = array() ) {
global $wgEnableParserCache;
- wfProfileIn( __METHOD__ );
-
- $options += array( 'changed' => true, 'created' => false, 'oldcountable' => null );
+ $options += array(
+ 'changed' => true,
+ 'created' => false,
+ 'moved' => false,
+ 'oldcountable' => null
+ );
$content = $revision->getContent();
// Parse the text
@@ -2186,7 +2179,7 @@ class WikiPage implements Page, IDBAccessObject {
// already pre-save transformed once.
if ( !$this->mPreparedEdit || $this->mPreparedEdit->output->getFlag( 'vary-revision' ) ) {
wfDebug( __METHOD__ . ": No prepared edit or vary-revision is set...\n" );
- $editInfo = $this->prepareContentForEdit( $content, $revision->getId(), $user );
+ $editInfo = $this->prepareContentForEdit( $content, $revision, $user );
} else {
wfDebug( __METHOD__ . ": No vary-revision, using prepared edit...\n" );
$editInfo = $this->mPreparedEdit;
@@ -2208,18 +2201,18 @@ class WikiPage implements Page, IDBAccessObject {
DataUpdate::runUpdates( $updates );
}
- wfRunHooks( 'ArticleEditUpdates', array( &$this, &$editInfo, $options['changed'] ) );
+ Hooks::run( 'ArticleEditUpdates', array( &$this, &$editInfo, $options['changed'] ) );
- if ( wfRunHooks( 'ArticleEditUpdatesDeleteFromRecentchanges', array( &$this ) ) ) {
- if ( 0 == mt_rand( 0, 99 ) ) {
- // Flush old entries from the `recentchanges` table; we do this on
- // random requests so as to avoid an increase in writes for no good reason
- RecentChange::purgeExpiredChanges();
- }
+ if ( Hooks::run( 'ArticleEditUpdatesDeleteFromRecentchanges', array( &$this ) ) ) {
+ JobQueueGroup::singleton()->push( array(
+ // Flush old entries from the `recentchanges` table
+ RecentChangesUpdateJob::newPurgeJob(),
+ // Update the cached list of active users
+ RecentChangesUpdateJob::newCacheUpdateJob()
+ ) );
}
if ( !$this->exists() ) {
- wfProfileOut( __METHOD__ );
return;
}
@@ -2227,7 +2220,9 @@ class WikiPage implements Page, IDBAccessObject {
$title = $this->mTitle->getPrefixedDBkey();
$shortTitle = $this->mTitle->getDBkey();
- if ( !$options['changed'] ) {
+ if ( $options['oldcountable'] === 'no-change' ||
+ ( !$options['changed'] && !$options['moved'] )
+ ) {
$good = 0;
} elseif ( $options['created'] ) {
$good = (int)$this->isCountable( $editInfo );
@@ -2255,7 +2250,7 @@ class WikiPage implements Page, IDBAccessObject {
wfDebug( __METHOD__ . ": invalid username\n" );
} else {
// Allow extensions to prevent user notification when a new message is added to their talk page
- if ( wfRunHooks( 'ArticleEditUpdateNewTalk', array( &$this, $recipient ) ) ) {
+ if ( Hooks::run( 'ArticleEditUpdateNewTalk', array( &$this, $recipient ) ) ) {
if ( User::isIP( $shortTitle ) ) {
// An anonymous user
$recipient->setNewtalk( true, $revision );
@@ -2284,7 +2279,6 @@ class WikiPage implements Page, IDBAccessObject {
self::onArticleEdit( $this->mTitle );
}
- wfProfileOut( __METHOD__ );
}
/**
@@ -2315,14 +2309,13 @@ class WikiPage implements Page, IDBAccessObject {
* @param User $user The relevant user
* @param string $comment Comment submitted
* @param bool $minor Whereas it's a minor modification
- * @param string $serialisation_format Format for storing the content in the database
+ * @param string $serialFormat Format for storing the content in the database
*/
public function doQuickEditContent( Content $content, User $user, $comment = '', $minor = false,
- $serialisation_format = null
+ $serialFormat = null
) {
- wfProfileIn( __METHOD__ );
- $serialized = $content->serialize( $serialisation_format );
+ $serialized = $content->serialize( $serialFormat );
$dbw = wfGetDB( DB_MASTER );
$revision = new Revision( array(
@@ -2338,9 +2331,8 @@ class WikiPage implements Page, IDBAccessObject {
$revision->insertOn( $dbw );
$this->updateRevisionOn( $dbw, $revision );
- wfRunHooks( 'NewRevisionFromEditComplete', array( $this, $revision, false, $user ) );
+ Hooks::run( 'NewRevisionFromEditComplete', array( $this, $revision, false, $user ) );
- wfProfileOut( __METHOD__ );
}
/**
@@ -2437,7 +2429,7 @@ class WikiPage implements Page, IDBAccessObject {
$logRelationsField = null;
if ( $id ) { // Protection of existing page
- if ( !wfRunHooks( 'ArticleProtect', array( &$this, &$user, $limit, $reason ) ) ) {
+ if ( !Hooks::run( 'ArticleProtect', array( &$this, &$user, $limit, $reason ) ) ) {
return Status::newGood();
}
@@ -2517,8 +2509,8 @@ class WikiPage implements Page, IDBAccessObject {
__METHOD__
);
- wfRunHooks( 'NewRevisionFromEditComplete', array( $this, $nullRevision, $latest, $user ) );
- wfRunHooks( 'ArticleProtectComplete', array( &$this, &$user, $limit, $reason ) );
+ Hooks::run( 'NewRevisionFromEditComplete', array( $this, $nullRevision, $latest, $user ) );
+ Hooks::run( 'ArticleProtectComplete', array( &$this, &$user, $limit, $reason ) );
} else { // Protection of non-existing page (also known as "title protection")
// Cascade protection is meaningless in this case
$cascade = false;
@@ -2780,7 +2772,7 @@ class WikiPage implements Page, IDBAccessObject {
}
$user = is_null( $user ) ? $wgUser : $user;
- if ( !wfRunHooks( 'ArticleDelete', array( &$this, &$user, &$reason, &$error, &$status ) ) ) {
+ if ( !Hooks::run( 'ArticleDelete', array( &$this, &$user, &$reason, &$error, &$status ) ) ) {
if ( $status->isOK() ) {
// Hook aborted but didn't set a fatal status
$status->fatal( 'delete-hook-aborted' );
@@ -2896,7 +2888,7 @@ class WikiPage implements Page, IDBAccessObject {
$this->doDeleteUpdates( $id, $content );
- wfRunHooks( 'ArticleDeleteComplete', array( &$this, &$user, $reason, $id, $content, $logEntry ) );
+ Hooks::run( 'ArticleDeleteComplete', array( &$this, &$user, $reason, $id, $content, $logEntry ) );
$status->value = $logid;
return $status;
}
@@ -3031,8 +3023,8 @@ class WikiPage implements Page, IDBAccessObject {
// Get the last edit not by this guy...
// Note: these may not be public values
- $user = intval( $current->getRawUser() );
- $user_text = $dbw->addQuotes( $current->getRawUserText() );
+ $user = intval( $current->getUser( Revision::RAW ) );
+ $user_text = $dbw->addQuotes( $current->getUserText( Revision::RAW ) );
$s = $dbw->selectRow( 'revision',
array( 'rev_id', 'rev_timestamp', 'rev_deleted' ),
array( 'rev_page' => $current->getPage(),
@@ -3075,7 +3067,7 @@ class WikiPage implements Page, IDBAccessObject {
}
// Generate the edit summary if necessary
- $target = Revision::newFromId( $s->rev_id );
+ $target = Revision::newFromId( $s->rev_id, Revision::READ_LATEST );
if ( empty( $summary ) ) {
if ( $from == '' ) { // no public user name
$summary = wfMessage( 'revertpage-nouser' );
@@ -3138,7 +3130,7 @@ class WikiPage implements Page, IDBAccessObject {
$revId = $status->value['revision']->getId();
- wfRunHooks( 'ArticleRollbackComplete', array( $this, $guser, $target, $current ) );
+ Hooks::run( 'ArticleRollbackComplete', array( $this, $guser, $target, $current ) );
$resultDetails = array(
'summary' => $summary,
@@ -3161,13 +3153,9 @@ class WikiPage implements Page, IDBAccessObject {
*
* @param Title $title
*/
- public static function onArticleCreate( $title ) {
+ public static function onArticleCreate( Title $title ) {
// Update existence markers on article/talk tabs...
- if ( $title->isTalkPage() ) {
- $other = $title->getSubjectPage();
- } else {
- $other = $title->getTalkPage();
- }
+ $other = $title->getOtherPage();
$other->invalidateCache();
$other->purgeSquid();
@@ -3182,13 +3170,9 @@ class WikiPage implements Page, IDBAccessObject {
*
* @param Title $title
*/
- public static function onArticleDelete( $title ) {
+ public static function onArticleDelete( Title $title ) {
// Update existence markers on article/talk tabs...
- if ( $title->isTalkPage() ) {
- $other = $title->getSubjectPage();
- } else {
- $other = $title->getTalkPage();
- }
+ $other = $title->getOtherPage();
$other->invalidateCache();
$other->purgeSquid();
@@ -3227,10 +3211,8 @@ class WikiPage implements Page, IDBAccessObject {
* Purge caches on page update etc
*
* @param Title $title
- * @todo Verify that $title is always a Title object (and never false or
- * null), add Title hint to parameter $title.
*/
- public static function onArticleEdit( $title ) {
+ public static function onArticleEdit( Title $title ) {
// Invalidate caches of articles which include this page
DeferredUpdates::addHTMLCacheUpdate( $title, 'templatelinks' );
@@ -3390,82 +3372,52 @@ class WikiPage implements Page, IDBAccessObject {
foreach ( $added as $catName ) {
$cat = Category::newFromName( $catName );
- wfRunHooks( 'CategoryAfterPageAdded', array( $cat, $that ) );
+ Hooks::run( 'CategoryAfterPageAdded', array( $cat, $that ) );
}
foreach ( $deleted as $catName ) {
$cat = Category::newFromName( $catName );
- wfRunHooks( 'CategoryAfterPageRemoved', array( $cat, $that ) );
+ Hooks::run( 'CategoryAfterPageRemoved', array( $cat, $that ) );
}
}
);
}
/**
- * Updates cascading protections
+ * Opportunistically enqueue link update jobs given fresh parser output if useful
*
- * @param ParserOutput $parserOutput ParserOutput object for the current version
+ * @param ParserOutput $parserOutput Current version page output
+ * @since 1.25
*/
- public function doCascadeProtectionUpdates( ParserOutput $parserOutput ) {
- if ( wfReadOnly() || !$this->mTitle->areRestrictionsCascading() ) {
+ public function triggerOpportunisticLinksUpdate( ParserOutput $parserOutput ) {
+ if ( wfReadOnly() ) {
return;
}
- // templatelinks or imagelinks tables may have become out of sync,
- // especially if using variable-based transclusions.
- // For paranoia, check if things have changed and if
- // so apply updates to the database. This will ensure
- // that cascaded protections apply as soon as the changes
- // are visible.
-
- // Get templates from templatelinks and images from imagelinks
- $id = $this->getId();
-
- $dbLinks = array();
-
- $dbr = wfGetDB( DB_SLAVE );
- $res = $dbr->select( array( 'templatelinks' ),
- array( 'tl_namespace', 'tl_title' ),
- array( 'tl_from' => $id ),
- __METHOD__
- );
-
- foreach ( $res as $row ) {
- $dbLinks["{$row->tl_namespace}:{$row->tl_title}"] = true;
+ if ( !Hooks::run( 'OpportunisticLinksUpdate', array( $this, $this->mTitle, $parserOutput ) ) ) {
+ return;
}
- $dbr = wfGetDB( DB_SLAVE );
- $res = $dbr->select( array( 'imagelinks' ),
- array( 'il_to' ),
- array( 'il_from' => $id ),
- __METHOD__
- );
-
- foreach ( $res as $row ) {
- $dbLinks[NS_FILE . ":{$row->il_to}"] = true;
+ if ( $this->mTitle->areRestrictionsCascading() ) {
+ // If the page is cascade protecting, the links should really be up-to-date
+ $params = array( 'prioritize' => true );
+ } elseif ( $parserOutput->hasDynamicContent() ) {
+ // Assume the output contains time/random based magic words
+ $params = array();
+ } else {
+ // If the inclusions are deterministic, the edit-triggered link jobs are enough
+ return;
}
- // Get templates and images from parser output.
- $poLinks = array();
- foreach ( $parserOutput->getTemplates() as $ns => $templates ) {
- foreach ( $templates as $dbk => $id ) {
- $poLinks["$ns:$dbk"] = true;
- }
- }
- foreach ( $parserOutput->getImages() as $dbk => $id ) {
- $poLinks[NS_FILE . ":$dbk"] = true;
+ // Check if the last link refresh was before page_touched
+ if ( $this->getLinksTimestamp() < $this->getTouched() ) {
+ JobQueueGroup::singleton()->push( EnqueueJob::newFromLocalJobs(
+ new JobSpecification( 'refreshLinks', $params, array(), $this->mTitle )
+ ) );
+ return;
}
- // Get the diff
- $links_diff = array_diff_key( $poLinks, $dbLinks );
-
- if ( count( $links_diff ) > 0 ) {
- // Whee, link updates time.
- // Note: we are only interested in links here. We don't need to get
- // other DataUpdate items from the parser output.
- $u = new LinksUpdate( $this->mTitle, $parserOutput, false );
- $u->doUpdate();
- }
+ return;
}
/**
@@ -3548,7 +3500,7 @@ class WikiPage implements Page, IDBAccessObject {
$updates = $content->getDeletionUpdates( $this );
}
- wfRunHooks( 'WikiPageDeletionUpdates', array( $this, $content, &$updates ) );
+ Hooks::run( 'WikiPageDeletionUpdates', array( $this, $content, &$updates ) );
return $updates;
}
}