=== New features in 1.25 ===
* (bug 58139) ResourceLoaderFileModule now supports language fallback
for 'languageScripts'.
+* Added a new hook, "ContentAlterParserOutput", to allow extensions to modify the
+ parser output for a content object before links update.
=== Bug fixes in 1.25 ===
ParserOutput object.
&$output: ParserOutput, to manipulate or replace
+'ContentAlterParserOutput': Modify parser output for a given content object.
+Called by Content::getParserOutput after parsing has finished. Can be used
+for changes that depend on the result of the parsing but have to be done
+before LinksUpdate is called (such as adding tracking categories based on
+the rendered HTML).
+$content: The Content to render
+$title: Title of the page, as context
+$parserOutput: ParserOutput to manipulate
+
'ConvertContent': Called by AbstractContent::convert when a conversion to another
content model is requested.
$content: The Content object to be converted.
'tagfilter',
20,
$selected,
- array( 'class' => 'mw-tagfilter-input', 'id' => 'tagfilter' )
+ array( 'class' => 'mw-tagfilter-input mw-ui-input mw-ui-input-inline', 'id' => 'tagfilter' )
)
);
$logid = $logEntry->insert();
$logEntry->publish( $logid );
}
-
-}
\ No newline at end of file
+}
);
$context = new ResourceLoaderContext( $resourceLoader, new FauxRequest( $query ) );
-
// Extract modules that know they're empty and see if we have one or more
// raw modules
$isRaw = false;
// Unlike SpecialPage itself, we want the canonical forms of both
// canonical and alias title forms...
$keys = array();
- foreach ( SpecialPageFactory::getNames() as $page ) {
+ foreach ( SpecialPageFactory::getNames() as $page ) {
$keys[$wgContLang->caseFold( $page )] = $page;
}
if ( $params['activeusers'] ) {
// Update active user cache
- SpecialActiveUsers::mergeActiveUsers( 600, $activeUserDays );
+ SpecialActiveUsers::mergeActiveUsers( 300, $activeUserDays );
}
$db = $this->getDB();
}
protected function doGetStatus( $virtualKey ) {
- return array( 'lastID' => null, 'asOfTime' => null, 'epoch' => null ) ;
+ return array( 'lastID' => null, 'asOfTime' => null, 'epoch' => null );
}
}
$options->setRedirectTarget( $oldRedir );
}
+ wfRunHooks( 'ContentAlterParserOutput', array( $this, $title, $po ) );
+
return $po;
}
if ( !is_null( $identity ) ) {
// then we want to get the identity column value we were assigned and save it off
$row = $ret->fetchObject();
- if( is_object( $row ) ){
+ if ( is_object( $row ) ) {
$this->mInsertId = $row->$identity;
}
}
$that = $this;
$work = new PoolCounterWorkViaCallback( 'GetLocalFileCopy', sha1( $this->getName() ),
array(
- 'doWork' => function() use ( $that ) {
+ 'doWork' => function () use ( $that ) {
return $that->getLocalRefPath();
}
)
function __construct( $address, $name = null, $realName = null ) {
if ( is_object( $address ) && $address instanceof User ) {
// Old calling format, now deprecated
- wfDeprecated( __METHOD__ . ' with a User object' , '1.24' );
+ wfDeprecated( __METHOD__ . ' with a User object', '1.24' );
$this->address = $address->getEmail();
$this->name = $address->getName();
$this->realName = $address->getRealName();
/**
* Return an XML string describing the DjVu image
- * @return string
+ * @return string|bool
*/
function retrieveMetaData() {
global $wgDjvuToXML, $wgDjvuDump, $wgDjvuTxt;
wfProfileIn( __METHOD__ );
+ if ( !$this->isValid() ) {
+ return false;
+ }
+
if ( isset( $wgDjvuDump ) ) {
# djvudump is faster as of version 3.5
# http://sourceforge.net/tracker/index.php?func=detail&aid=1704049&group_id=32953&atid=406583
$query = $request->getValues();
unset( $query['rdfrom'] );
unset( $query['title'] );
+ if ( $this->getTitle()->isRedirect() ) {
+ // Prevent double redirects
+ $query['redirect'] = 'no';
+ }
$redirectTargetUrl = $this->getTitle()->getLinkURL( $query );
if ( isset( $this->mRedirectedFrom ) ) {
$attrs['class'] = "mw-{$type}link";
}
-
return Linker::linkKnown(
$this->getTitle(),
$text,
}
/**
- * Add a tracking category, getting the title from a system message,
- * or print a debug message if the title is invalid.
- *
- * Please add any message that you use with this function to
- * $wgTrackingCategories. That way they will be listed on
- * Special:TrackingCategories.
- *
+ * @see ParserOutput::addTrackingCategory()
* @param string $msg Message key
* @return bool Whether the addition was successful
*/
public function addTrackingCategory( $msg ) {
- if ( $this->mTitle->getNamespace() === NS_SPECIAL ) {
- wfDebug( __METHOD__ . ": Not adding tracking category $msg to special page!\n" );
- return false;
- }
- // Important to parse with correct title (bug 31469)
- $cat = wfMessage( $msg )
- ->title( $this->getTitle() )
- ->inContentLanguage()
- ->text();
-
- # Allow tracking categories to be disabled by setting them to "-"
- if ( $cat === '-' ) {
- return false;
- }
-
- $containerCategory = Title::makeTitleSafe( NS_CATEGORY, $cat );
- if ( $containerCategory ) {
- $this->mOutput->addCategory( $containerCategory->getDBkey(), $this->getDefaultSort() );
- return true;
- } else {
- wfDebug( __METHOD__ . ": [[MediaWiki:$msg]] is not a valid title!\n" );
- return false;
- }
+ return $this->mOutput->addTrackingCategory( $msg, $this->mTitle );
}
/**
$this->mPreventClickjacking = $this->mPreventClickjacking || $out->getPreventClickjacking();
}
+ /**
+ * Add a tracking category, getting the title from a system message,
+ * or print a debug message if the title is invalid.
+ *
+ * Please add any message that you use with this function to
+ * $wgTrackingCategories. That way they will be listed on
+ * Special:TrackingCategories.
+ *
+ * @param string $msg Message key
+ * @param Title $title title of the page which is being tracked
+ * @return bool Whether the addition was successful
+ * @since 1.25
+ */
+ public function addTrackingCategory( $msg, $title ) {
+ if ( $title->getNamespace() === NS_SPECIAL ) {
+ wfDebug( __METHOD__ . ": Not adding tracking category $msg to special page!\n" );
+ return false;
+ }
+
+ // Important to parse with correct title (bug 31469)
+ $cat = wfMessage( $msg )
+ ->title( $title )
+ ->inContentLanguage()
+ ->text();
+
+ # Allow tracking categories to be disabled by setting them to "-"
+ if ( $cat === '-' ) {
+ return false;
+ }
+
+ $containerCategory = Title::makeTitleSafe( NS_CATEGORY, $cat );
+ if ( $containerCategory ) {
+ $this->addCategory( $containerCategory->getDBkey(), $this->getProperty( 'defaultsort' ) ?: '' );
+ return true;
+ } else {
+ wfDebug( __METHOD__ . ": [[MediaWiki:$msg]] is not a valid title!\n" );
+ return false;
+ }
+ }
+
/**
* Override the title to be used for display
* -- this is assumed to have been validated
$modifiedTime = 1; // wfTimestamp() interprets 0 as "now"
$titleInfo = $this->getTitleInfo( $context );
if ( count( $titleInfo ) ) {
- $mtimes = array_map( function( $value ) {
+ $mtimes = array_map( function ( $value ) {
return $value['timestamp'];
}, $titleInfo );
$modifiedTime = max( $modifiedTime, max( $mtimes ) );
$dbw->startAtomic( __METHOD__ );
$ok = $dbw->delete( 'sites', '*', __METHOD__ );
$ok = $dbw->delete( 'site_identifiers', '*', __METHOD__ ) && $ok;
- $dbw->endAtomic( __METHOD__);
+ $dbw->endAtomic( __METHOD__ );
$this->reset();
array( 'activeusers-intro', $this->getLanguage()->formatNum( $days ) ) );
// Occasionally merge in new updates
- $seconds = min( self::mergeActiveUsers( 600, $days ), $days * 86400 );
+ $seconds = min( self::mergeActiveUsers( 300, $days ), $days * 86400 );
// Mention the level of staleness
$out->addWikiMsg( 'cachedspecial-viewing-cached-ttl',
$this->getLanguage()->formatDuration( $seconds ) );
$this->msg( 'categories' )->text(),
Xml::inputLabel(
$this->msg( 'categoriesfrom' )->text(),
- 'from', 'from', 20, $from, array( 'class' => 'mw-ui-input-inline') ) .
+ 'from', 'from', 20, $from, array( 'class' => 'mw-ui-input-inline' ) ) .
' ' .
Xml::submitButton(
$this->msg( 'allpagessubmit' )->text(),
$form->setTableId( 'mw-changeemail-table' );
$form->setWrapperLegend( false );
$form->setSubmitTextMsg( 'changeemail-submit' );
- $form->addHiddenField( 'returnto', $this->getRequest()->getVal( 'returnto' ) );
+ $form->addHiddenFields( $this->getRequest()->getValues( 'returnto', 'returntoquery' ) );
}
public function onSubmit( array $data ) {
}
public function onSuccess() {
- $titleObj = Title::newFromText( $this->getRequest()->getVal( 'returnto' ) );
+ $request = $this->getRequest();
+
+ $titleObj = Title::newFromText( $request->getVal( 'returnto' ) );
if ( !$titleObj instanceof Title ) {
$titleObj = Title::newMainPage();
}
+ $query = $request->getVal( 'returntoquery' );
if ( $this->status->value === true ) {
- $this->getOutput()->redirect( $titleObj->getFullURL() );
+ $this->getOutput()->redirect( $titleObj->getFullURL( $query ) );
} elseif ( $this->status->value === 'eauth' ) {
# Notify user that a confirmation email has been sent...
$this->getOutput()->wrapWikiMsg( "<div class='error' style='clear: both;'>\n$1\n</div>",
'eauthentsent', $this->getUser()->getName() );
- $this->getOutput()->addReturnTo( $titleObj ); // just show the link to go back
+ $this->getOutput()->addReturnTo( $titleObj, wfCgiToArray( $query ) ); // just show the link to go back
}
}
if ( $tagFilter ) {
$filterSelection = Html::rawElement(
'td',
- array( 'class' => 'mw-label' ),
- array_shift( $tagFilter )
- );
- $filterSelection .= Html::rawElement(
- 'td',
- array( 'class' => 'mw-input' ),
- implode( ' ', $tagFilter )
+ array(),
+ array_shift( $tagFilter ) . implode( ' ', $tagFilter )
);
} else {
$filterSelection = Html::rawElement( 'td', array( 'colspan' => 2 ), '' );
'target',
$this->opts['target'],
'text',
- array( 'size' => '40', 'required' => '', 'class' => 'mw-input' ) +
+ array( 'size' => '40', 'required' => '', 'class' => 'mw-input mw-ui-input-inline' ) +
( $this->opts['target'] ? array() : array( 'autofocus' )
)
);
$namespaceSelection = Xml::tags(
'td',
- array( 'class' => 'mw-label' ),
+ array(),
Xml::label(
$this->msg( 'namespace' )->text(),
'namespace',
''
- )
- );
- $namespaceSelection .= Html::rawElement(
- 'td',
- null,
+ ) .
Html::namespaceSelector(
array( 'selected' => $this->opts['namespace'], 'all' => '' ),
array(
$deletedOnlyCheck . $checkLabelTopOnly . $checkLabelNewOnly
);
+ $className = 'mw-submit';
+ if ( $this->getConfig( 'UseMediaWikiUIEverywhere') ) {
+ $className .= ' mw-ui-button mw-ui-progressive';
+ }
+
$dateSelectionAndSubmit = Xml::tags( 'td', array( 'colspan' => 2 ),
Xml::dateMenu(
$this->opts['year'] === '' ? MWTimestamp::getInstance()->format( 'Y' ) : $this->opts['year'],
) . ' ' .
Xml::submitButton(
$this->msg( 'sp-contributions-submit' )->text(),
- array( 'class' => 'mw-submit' )
+ array( 'class' => $className )
)
);
);
array_walk( $tags, function ( &$value ) {
- $value = '<' . htmlspecialchars( $value ) . '>';
+ // Bidirectional isolation improves readability in RTL wikis
+ $value = Html::element(
+ 'bdi',
+ // Prevent < and > from slipping to another line
+ array(
+ 'style' => 'white-space: nowrap;',
+ ),
+ "<$value>"
+ );
} );
+
$out .= $this->listToText( $tags );
} else {
$out = '';
* @return boolean
*/
protected function existenceCheck( Title $title ) {
- return (bool) wfFindFile( $title );
+ return (bool)wfFindFile( $title );
}
function getQueryInfo() {
rsort( $sizes );
foreach ( $sizes as $size ) {
- $jobs []= new ThumbnailRenderJob( $this->getLocalFile()->getTitle(), array(
+ $jobs[] = new ThumbnailRenderJob( $this->getLocalFile()->getTitle(), array(
'transformParams' => array( 'width' => $size ),
) );
}
'size-megabytes',
'size-gigabytes',
'largefileserver',
+ 'editwarning-warning',
+ // editwarning-warning uses {{int:prefs-editing}}
+ 'prefs-editing',
),
'dependencies' => array(
'jquery.spinner',
+ 'mediawiki.jqueryMsg',
'mediawiki.api',
'mediawiki.libs.jpegmeta',
'mediawiki.Title',
table.mw-userrights-groups * th {
padding-right: 1.5em;
}
+
+/* Special:Contributions */
+.mw-contributions-form select {
+ vertical-align: middle;
+}
'mediawiki.special.changeslist',
$styleModules,
'has mediawiki.special.changeslist'
- );
+ );
$this->assertContains(
'mediawiki.special.changeslist.enhanced',
$this->assertEquals( '', $html );
}
- /**
- * @todo more tests for actual formatting, this is more of a smoke test
- */
- public function testEndRecentChangesList() {
+ /**
+ * @todo more tests for actual formatting, this is more of a smoke test
+ */
+ public function testEndRecentChangesList() {
$enhancedChangesList = $this->newEnhancedChangesList();
$enhancedChangesList->beginRecentChangesList();
preg_match_all( '/td class="mw-enhanced-rc-nested"/', $html, $matches );
$this->assertCount( 2, $matches[0] );
- }
+ }
/**
* @return EnhancedChangesList
$conf->set( 'one', '3' );
$this->assertEquals( '3', $conf->get( 'one' ) );
}
-}
\ No newline at end of file
+}
$ma = new MailAddress( 'some@email.com', 'UserName', 'A real name' );
$this->assertEquals( $ma->toString(), (string)$ma );
}
-
-}
\ No newline at end of file
+}
public function specialPageProvider() {
return array(
'class name' => array( 'SpecialAllPages', false ),
- 'closure' => array( function() {
+ 'closure' => array( function () {
return new SpecialAllPages();
}, false ),
- 'function' => array( array( $this, 'newSpecialAllPages' ), false ),
+ 'function' => array( array( $this, 'newSpecialAllPages' ), false ),
);
}