';
}
return $text;
}
/**
* Display a page stating that the Wiki is in read-only mode,
* and optionally show the source of the page that the user
* was trying to edit. Should only be called (for this
* purpose) after wfReadOnly() has returned true.
*
* For historical reasons, this function is _also_ used to
* show the error message when a user tries to edit a page
* they are not allowed to edit. (Unless it's because they're
* blocked, then we show blockedPage() instead.) In this
* case, the second parameter should be set to true and a list
* of reasons supplied as the third parameter.
*
* @todo Needs to be split into multiple functions.
*
* @param string $source Source code to show (or null).
* @param bool $protected Is this a permissions error?
* @param array $reasons List of reasons for this error, as returned by Title::getUserPermissionsErrors().
*/
public function readOnlyPage( $source = null, $protected = false, $reasons = array(), $action = null ) {
global $wgUser, $wgTitle;
$skin = $wgUser->getSkin();
$this->setRobotPolicy( 'noindex,nofollow' );
$this->setArticleRelated( false );
// If no reason is given, just supply a default "I can't let you do
// that, Dave" message. Should only occur if called by legacy code.
if ( $protected && empty($reasons) ) {
$reasons[] = array( 'badaccess-group0' );
}
if ( !empty($reasons) ) {
// Permissions error
if( $source ) {
$this->setPageTitle( wfMsg( 'viewsource' ) );
$this->setSubtitle( wfMsg( 'viewsourcefor', $skin->makeKnownLinkObj( $wgTitle ) ) );
} else {
$this->setPageTitle( wfMsg( 'badaccess' ) );
}
$this->addWikiText( $this->formatPermissionsErrorMessage( $reasons, $action ) );
} else {
// Wiki is read only
$this->setPageTitle( wfMsg( 'readonly' ) );
$reason = wfReadOnlyReason();
$this->addWikiMsg( 'readonlytext', $reason );
}
// Show source, if supplied
if( is_string( $source ) ) {
$this->addWikiMsg( 'viewsourcetext' );
$text = Xml::openElement( 'textarea',
array( 'id' => 'wpTextbox1',
'name' => 'wpTextbox1',
'cols' => $wgUser->getOption( 'cols' ),
'rows' => $wgUser->getOption( 'rows' ),
'readonly' => 'readonly' ) );
$text .= htmlspecialchars( $source );
$text .= Xml::closeElement( 'textarea' );
$this->addHTML( $text );
// Show templates used by this article
$skin = $wgUser->getSkin();
$article = new Article( $wgTitle );
$this->addHTML( $skin->formatTemplates( $article->getUsedTemplates() ) );
}
# If the title doesn't exist, it's fairly pointless to print a return
# link to it. After all, you just tried editing it and couldn't, so
# what's there to do there?
if( $wgTitle->exists() ) {
$this->returnToMain( null, $wgTitle );
}
}
/** @deprecated */
public function fatalError( $message ) {
wfDeprecated( __METHOD__ );
throw new FatalError( $message );
}
/** @deprecated */
public function unexpectedValueError( $name, $val ) {
wfDeprecated( __METHOD__ );
throw new FatalError( wfMsg( 'unexpected', $name, $val ) );
}
/** @deprecated */
public function fileCopyError( $old, $new ) {
wfDeprecated( __METHOD__ );
throw new FatalError( wfMsg( 'filecopyerror', $old, $new ) );
}
/** @deprecated */
public function fileRenameError( $old, $new ) {
wfDeprecated( __METHOD__ );
throw new FatalError( wfMsg( 'filerenameerror', $old, $new ) );
}
/** @deprecated */
public function fileDeleteError( $name ) {
wfDeprecated( __METHOD__ );
throw new FatalError( wfMsg( 'filedeleteerror', $name ) );
}
/** @deprecated */
public function fileNotFoundError( $name ) {
wfDeprecated( __METHOD__ );
throw new FatalError( wfMsg( 'filenotfound', $name ) );
}
public function showFatalError( $message ) {
$this->setPageTitle( wfMsg( "internalerror" ) );
$this->setRobotPolicy( "noindex,nofollow" );
$this->setArticleRelated( false );
$this->enableClientCache( false );
$this->mRedirect = '';
$this->mBodytext = $message;
}
public function showUnexpectedValueError( $name, $val ) {
$this->showFatalError( wfMsg( 'unexpected', $name, $val ) );
}
public function showFileCopyError( $old, $new ) {
$this->showFatalError( wfMsg( 'filecopyerror', $old, $new ) );
}
public function showFileRenameError( $old, $new ) {
$this->showFatalError( wfMsg( 'filerenameerror', $old, $new ) );
}
public function showFileDeleteError( $name ) {
$this->showFatalError( wfMsg( 'filedeleteerror', $name ) );
}
public function showFileNotFoundError( $name ) {
$this->showFatalError( wfMsg( 'filenotfound', $name ) );
}
/**
* Add a "return to" link pointing to a specified title
*
* @param Title $title Title to link
*/
public function addReturnTo( $title ) {
global $wgUser;
$link = wfMsg( 'returnto', $wgUser->getSkin()->makeLinkObj( $title ) );
$this->addHtml( "
{$link}
\n" );
}
/**
* Add a "return to" link pointing to a specified title,
* or the title indicated in the request, or else the main page
*
* @param null $unused No longer used
* @param Title $returnto Title to return to
*/
public function returnToMain( $unused = null, $returnto = NULL ) {
global $wgRequest;
if ( $returnto == NULL ) {
$returnto = $wgRequest->getText( 'returnto' );
}
if ( '' === $returnto ) {
$returnto = Title::newMainPage();
}
if ( is_object( $returnto ) ) {
$titleObj = $returnto;
} else {
$titleObj = Title::newFromText( $returnto );
}
if ( !is_object( $titleObj ) ) {
$titleObj = Title::newMainPage();
}
$this->addReturnTo( $titleObj );
}
/**
* This function takes the title (first item of mGoodLinks), categories, existing and broken links for the page
* and uses the first 10 of them for META keywords
*
* @param ParserOutput &$parserOutput
*/
private function addKeywords( &$parserOutput ) {
global $wgTitle;
$this->addKeyword( $wgTitle->getPrefixedText() );
$count = 1;
$links2d =& $parserOutput->getLinks();
if ( !is_array( $links2d ) ) {
return;
}
foreach ( $links2d as $dbkeys ) {
foreach( $dbkeys as $dbkey => $unused ) {
$this->addKeyword( $dbkey );
if ( ++$count > 10 ) {
break 2;
}
}
}
}
/**
* @return string The doctype, opening , and head element.
*/
public function headElement() {
global $wgDocType, $wgDTD, $wgContLanguageCode, $wgOutputEncoding, $wgMimeType;
global $wgXhtmlDefaultNamespace, $wgXhtmlNamespaces;
global $wgUser, $wgContLang, $wgUseTrackbacks, $wgTitle, $wgStyleVersion;
if( $wgMimeType == 'text/xml' || $wgMimeType == 'application/xhtml+xml' || $wgMimeType == 'application/xml' ) {
$ret = "\n";
} else {
$ret = '';
}
$ret .= "\n";
if ( '' == $this->getHTMLTitle() ) {
$this->setHTMLTitle( wfMsg( 'pagetitle', $this->getPageTitle() ));
}
$rtl = $wgContLang->isRTL() ? " dir='RTL'" : '';
$ret .= " $ns) {
$ret .= "xmlns:{$tag}=\"{$ns}\" ";
}
$ret .= "xml:lang=\"$wgContLanguageCode\" lang=\"$wgContLanguageCode\" $rtl>\n";
$ret .= "\n" . htmlspecialchars( $this->getHTMLTitle() ) . "\n";
$this->addMeta( "http:Content-type", "$wgMimeType; charset={$wgOutputEncoding}" );
$ret .= $this->getHeadLinks();
global $wgStylePath;
if( $this->isPrintable() ) {
$media = '';
} else {
$media = "media='print'";
}
$printsheet = htmlspecialchars( "$wgStylePath/common/wikiprintable.css?$wgStyleVersion" );
$ret .= "\n";
$sk = $wgUser->getSkin();
$ret .= $sk->getHeadScripts( $this->mAllowUserJs );
$ret .= $this->mScripts;
$ret .= $sk->getUserStyles();
$ret .= $this->getHeadItems();
if ($wgUseTrackbacks && $this->isArticleRelated())
$ret .= $wgTitle->trackbackRDF();
$ret .= "\n";
return $ret;
}
protected function addDefaultMeta() {
global $wgVersion;
$this->addMeta( "generator", "MediaWiki $wgVersion" );
$p = "{$this->mIndexPolicy},{$this->mFollowPolicy}";
if( $p !== 'index,follow' ) {
// http://www.robotstxt.org/wc/meta-user.html
// Only show if it's different from the default robots policy
$this->addMeta( 'robots', $p );
}
if ( count( $this->mKeywords ) > 0 ) {
$strip = array(
"/<.*?>/" => '',
"/_/" => ' '
);
$this->addMeta( 'keywords', preg_replace(array_keys($strip), array_values($strip),implode( ",", $this->mKeywords ) ) );
}
}
/**
* @return string HTML tag links to be put in the header.
*/
public function getHeadLinks() {
global $wgRequest, $wgFeed;
// Ideally this should happen earlier, somewhere. :P
$this->addDefaultMeta();
$tags = array();
foreach ( $this->mMetatags as $tag ) {
if ( 0 == strcasecmp( 'http:', substr( $tag[0], 0, 5 ) ) ) {
$a = 'http-equiv';
$tag[0] = substr( $tag[0], 5 );
} else {
$a = 'name';
}
$tags[] = Xml::element( 'meta',
array(
$a => $tag[0],
'content' => $tag[1] ) );
}
foreach ( $this->mLinktags as $tag ) {
$tags[] = Xml::element( 'link', $tag );
}
if( $wgFeed ) {
global $wgTitle;
foreach( $this->getSyndicationLinks() as $format => $link ) {
# Use the page name for the title (accessed through $wgTitle since
# there's no other way). In principle, this could lead to issues
# with having the same name for different feeds corresponding to
# the same page, but we can't avoid that at this low a level.
$tags[] = $this->feedLink(
$format,
$link,
wfMsg( "page-{$format}-feed", $wgTitle->getPrefixedText() ) ); # Used messages: 'page-rss-feed' and 'page-atom-feed' (for an easier grep)
}
# Recent changes feed should appear on every page (except recentchanges,
# that would be redundant). Put it after the per-page feed to avoid
# changing existing behavior. It's still available, probably via a
# menu in your browser.
$rctitle = SpecialPage::getTitleFor( 'Recentchanges' );
if ( $wgTitle->getPrefixedText() != $rctitle->getPrefixedText() ) {
global $wgSitename;
$tags[] = $this->feedLink(
'rss',
$rctitle->getFullURL( 'feed=rss' ),
wfMsg( 'site-rss-feed', $wgSitename ) );
$tags[] = $this->feedLink(
'atom',
$rctitle->getFullURL( 'feed=atom' ),
wfMsg( 'site-atom-feed', $wgSitename ) );
}
}
return implode( "\n\t\t", $tags ) . "\n";
}
/**
* Return URLs for each supported syndication format for this page.
* @return array associating format keys with URLs
*/
public function getSyndicationLinks() {
global $wgTitle, $wgFeedClasses;
$links = array();
if( $this->isSyndicated() ) {
if( is_string( $this->getFeedAppendQuery() ) ) {
$appendQuery = "&" . $this->getFeedAppendQuery();
} else {
$appendQuery = "";
}
foreach( $wgFeedClasses as $format => $class ) {
$links[$format] = $wgTitle->getLocalUrl( "feed=$format{$appendQuery}" );
}
}
return $links;
}
/**
* Generate a for an RSS feed.
*/
private function feedLink( $type, $url, $text ) {
return Xml::element( 'link', array(
'rel' => 'alternate',
'type' => "application/$type+xml",
'title' => $text,
'href' => $url ) );
}
/**
* Turn off regular page output and return an error reponse
* for when rate limiting has triggered.
*/
public function rateLimited() {
global $wgTitle;
$this->setPageTitle(wfMsg('actionthrottled'));
$this->setRobotPolicy( 'noindex,follow' );
$this->setArticleRelated( false );
$this->enableClientCache( false );
$this->mRedirect = '';
$this->clearHTML();
$this->setStatusCode(503);
$this->addWikiMsg( 'actionthrottledtext' );
$this->returnToMain( null, $wgTitle );
}
/**
* Show an "add new section" link?
*
* @return bool
*/
public function showNewSectionLink() {
return $this->mNewSectionLink;
}
/**
* Show a warning about slave lag
*
* If the lag is higher than $wgSlaveLagCritical seconds,
* then the warning is a bit more obvious. If the lag is
* lower than $wgSlaveLagWarning, then no warning is shown.
*
* @param int $lag Slave lag
*/
public function showLagWarning( $lag ) {
global $wgSlaveLagWarning, $wgSlaveLagCritical;
if( $lag >= $wgSlaveLagWarning ) {
$message = $lag < $wgSlaveLagCritical
? 'lag-warn-normal'
: 'lag-warn-high';
$warning = wfMsgExt( $message, 'parse', $lag );
$this->addHtml( "
\n{$warning}\n
\n" );
}
}
/**
* Add a wikitext-formatted message to the output.
* This is equivalent to:
*
* $wgOut->addWikiText( wfMsgNoTrans( ... ) )
*/
public function addWikiMsg( /*...*/ ) {
$args = func_get_args();
$name = array_shift( $args );
$this->addWikiMsgArray( $name, $args );
}
/**
* Add a wikitext-formatted message to the output.
* Like addWikiMsg() except the parameters are taken as an array
* instead of a variable argument list.
*
* $options is passed through to wfMsgExt(), see that function for details.
*/
public function addWikiMsgArray( $name, $args, $options = array() ) {
$options[] = 'parse';
$text = wfMsgExt( $name, $options, $args );
$this->addHTML( $text );
}
/**
* This function takes a number of message/argument specifications, wraps them in
* some overall structure, and then parses the result and adds it to the output.
*
* In the $wrap, $1 is replaced with the first message, $2 with the second, and so
* on. The subsequent arguments may either be strings, in which case they are the
* message names, or an arrays, in which case the first element is the message name,
* and subsequent elements are the parameters to that message.
*
* The special named parameter 'options' in a message specification array is passed
* through to the $options parameter of wfMsgExt().
*
* Don't use this for messages that are not in users interface language.
*
* For example:
*
* $wgOut->wrapWikiMsg( '
$1
', 'some-error' );
*
* Is equivalent to:
*
* $wgOut->addWikiText( '