* page of the given title.
*/
public function view() {
- global $wgUseFileCache, $wgUseETag, $wgDebugToolbar;
+ global $wgUseFileCache, $wgUseETag, $wgDebugToolbar, $wgMaxRedirects;
wfProfileIn( __METHOD__ );
$outputPage->setETag( $parserCache->getETag( $this, $parserOptions ) );
}
+ # Use the greatest of the page's timestamp or the timestamp of any
+ # redirect in the chain (bug 67849)
+ $timestamp = $this->mPage->getTouched();
+ if ( isset( $this->mRedirectedFrom ) ) {
+ $timestamp = max( $timestamp, $this->mRedirectedFrom->getTouched() );
+
+ # If there can be more than one redirect in the chain, we have
+ # to go through the whole chain too in case an intermediate
+ # redirect was changed.
+ if ( $wgMaxRedirects > 1 ) {
+ $titles = Revision::newFromTitle( $this->mRedirectedFrom )
+ ->getContent( Revision::FOR_THIS_USER, $user )
+ ->getRedirectChain();
+ $thisTitle = $this->getTitle();
+ foreach ( $titles as $title ) {
+ if ( Title::compare( $title, $thisTitle ) === 0 ) {
+ break;
+ }
+ $timestamp = max( $timestamp, $title->getTouched() );
+ }
+ }
+ }
+
# Is it client cached?
- if ( $outputPage->checkLastModified( $this->mPage->getTouched() ) ) {
+ if ( $outputPage->checkLastModified( $timestamp ) ) {
wfDebug( __METHOD__ . ": done 304\n" );
wfProfileOut( __METHOD__ );
* @param string $text Desired title text
* @return string
*/
- static function displaytitle( $parser, $text = '' ) {
+ static function displaytitle( $parser, $text = '', $uarg = '' ) {
global $wgRestrictDisplayTitle;
+ static $magicWords = null;
+ if ( is_null( $magicWords ) ) {
+ $magicWords = new MagicWordArray( array( 'displaytitle_noerror', 'displaytitle_noreplace' ) );
+ }
+ $arg = $magicWords->matchStartToEnd( $uarg );
+
// parse a limited subset of wiki markup (just the single quote items)
$text = $parser->doQuotes( $text );
) );
$title = Title::newFromText( Sanitizer::stripAllTags( $text ) );
- if ( !$wgRestrictDisplayTitle ) {
- $parser->mOutput->setDisplayTitle( $text );
- } elseif ( $title instanceof Title
+ if ( !$wgRestrictDisplayTitle ||
+ ( $title instanceof Title
&& !$title->hasFragment()
- && $title->equals( $parser->mTitle )
+ && $title->equals( $parser->mTitle ) )
) {
- $parser->mOutput->setDisplayTitle( $text );
+ $old = $parser->mOutput->getProperty( 'displaytitle' );
+ if ( $old === false || $arg !== 'displaytitle_noreplace' ) {
+ $parser->mOutput->setDisplayTitle( $text );
+ }
+ if ( $old !== false && $old !== $text && !$arg ) {
+ $converter = $parser->getConverterLanguage()->getConverter();
+ return '<span class="error">' .
+ wfMessage( 'duplicate-displaytitle',
+ // Message should be parsed, but these params should only be escaped.
+ $converter->markNoConversion( wfEscapeWikiText( $old ) ),
+ $converter->markNoConversion( wfEscapeWikiText( $text ) )
+ )->inContentLanguage()->text() .
+ '</span>';
+ }
}
return '';
"timezone-utc": "UTC",
"unknown_extension_tag": "Unknown extension tag \"$1\"",
"duplicate-defaultsort": "<strong>Warning:</strong> Default sort key \"$2\" overrides earlier default sort key \"$1\".",
+ "duplicate-displaytitle": "<strong>Warning:</strong> Display title \"$2\" overrides earlier display title \"$1\".",
"version": "Version",
"version-summary": "",
"version-extensions": "Installed extensions",
"timezone-utc": "{{optional}}",
"unknown_extension_tag": "This is an error shown when you use an unknown extension tag name.\n\nThis feature allows tags like <code><nowiki><pre></nowiki></code> to be called with a parser like <code><nowiki>{{#tag:pre}}</nowiki></code>.\n\nParameters:\n* $1 - the unknown extension tag name",
"duplicate-defaultsort": "See definition of [[w:Sorting|sort key]] on Wikipedia. Parameters:\n* $1 - old default sort key\n* $2 - new default sort key",
+ "duplicate-displaytitle": "Warning shown when a page has its display title set multiple times. Parameters:\n* $1 - old display title\n* $2 - new display title",
"version": "{{doc-special|Version}}\n{{Identical|Version}}",
"version-summary": "{{doc-specialpagesummary|version}}",
"version-extensions": "Header on [[Special:Version]].",
'url_query' => array( 0, 'QUERY' ),
'defaultsort_noerror' => array( 0, 'noerror' ),
'defaultsort_noreplace' => array( 0, 'noreplace' ),
+ 'displaytitle_noerror' => array( 0, 'noerror' ),
+ 'displaytitle_noreplace' => array( 0, 'noreplace' ),
'pagesincategory_all' => array( 0, 'all' ),
'pagesincategory_pages' => array( 0, 'pages' ),
'pagesincategory_subcats' => array( 0, 'subcats' ),
/**
* Execute a function as soon as one or more required modules are ready.
*
+ * If the required modules are already loaded, the function will be
+ * executed immediately and the modules will not be reloaded.
+ *
* Example of inline dependency on OOjs:
*
* mw.loader.using( 'oojs', function () {
// As a convenience feature, automatically restore warnings if they're
// still suppressed by the end of the test.
restoreWarnings();
+
+ // Check for (and clean up, if possible) incomplete animations/requests/etc.
+ if ( $.timers && $.timers.length !== 0 ) {
+ // Test may need to use fake timers, wait for animations or
+ // call $.fx.stop().
+ throw new Error( 'Unfinished animations: ' + $.timers.length );
+ }
+ if ( $.active !== undefined && $.active !== 0 ) {
+ // Test may need to use fake XHR, wait for requests or
+ // call abort().
+ throw new Error( 'Unfinished AJAX requests: ' + $.active );
+ }
}
};
};