images/[0-9a-f]
images/temp
images/thumb
+maintenance/dev/data/
+maintenance/.mweval_history
\ No newline at end of file
=== Changes since 1.19 beta 1 ===
* (bug 35014) Including a special page no longer sets the page's title to the
- included page
-* (bug 35019) Edit summaries are no longer transformed in notification e-mails
-* (bug 35152) Help message for e-mail is shown again in user preferences
+ included page.
+* (bug 35019) Edit summaries are no longer transformed in notification e-mails.
+* (bug 35152) Help message for e-mail is shown again in user preferences.
* (bug 34887) $3 and $4 parameters are now substituted correctly in message
- "movepage-moved"
+ "movepage-moved".
* (bug 34841) Edit links are no longer displayed when display old page versions
-* (bug 34889) User name should be normalized on Special:Contributions
-* (bug 35051) If heading has a trailing space after == then its name is not
- preloaded into edit summary on section edit
+* (bug 34889) User name should be normalized on Special:Contributions.
+* (bug 35051) If heading has a trailing space after == then its name is not
+ preloaded into edit summary on section edit.
* (bug 31417) New ID mw-content-text around the actual page text, without categories,
contentSub, ... The same div often also contains the class mw-content-ltr/rtl.
* (bug 35303) Proxy and DNS blacklist blocking works again
core parser functions which operate on strings, such as padleft.
* (bug 18295) Don't expose strip markers when a tag appears inside a link
inside a heading.
+* (bug 34907) Fixed exposure of tokens through load.php that could have facilitated
+ CSRF attacks
=== Configuration changes in 1.19 ===
* Removed SkinTemplateSetupPageCss hook; use BeforePageDisplay instead.
* (bug 32239) Removed $wgEnableTooltipsAndAccesskeys.
* Removed $wgVectorShowVariantName.
* Removed $wgExtensionAliasesFiles. Use $wgExtensionMessagesFiles.
+* Removed $wgResourceLoaderInlinePrivateModules, now always enabled.
=== New features in 1.19 ===
* (bug 19838) Add ability to get all interwiki prefixes also if the interwiki
200 status code instead of 404 for nonexistent articles.
* (bug 33447) Link to the broken image tracking category from Special:Wantedfiles.
* (bug 27724) Add timestamp to job queue.
-* (bug 30339) Implement SpecialPage for running javascript tests. Disabled by default, due to
- tests potentially being harmful, not to be run on a production wiki.
+* (bug 30339) Implement SpecialPage for running javascript tests. Disabled by default,
+ due to tests potentially being harmful, not to be run on a production wiki.
Enable by setting $wgEnableJavaScriptTest to true.
* Extensions can use the RequestContextCreateSkin hook to override what skin is
loaded in some contexts.
* Special:MovePage now has a dropdown menu for namespaces.
* (bug 34420) Special:Version now shows git HEAD sha1 when available.
* (bug 33952) Refactor mw.toolbar to allow dynamic additions at any time.
-* Now possible to specify separate section title and edit summary when adding a new section to a
- page via the edit API action.
+* Now possible to specify separate section title and edit summary when adding
+ a new section to a page via the edit API action.
=== Bug fixes in 1.19 ===
* $wgUploadNavigationUrl should be used for file redlinks if.
// Initialise common code.
if ( isset( $_SERVER['MW_COMPILED'] ) ) {
- require ( 'phase3/includes/WebStart.php' );
+ require ( 'core/includes/WebStart.php' );
} else {
require ( dirname( __FILE__ ) . '/includes/WebStart.php' );
}
--- /dev/null
+*
+!README
+!.gitignore
define( 'MW_NO_OUTPUT_COMPRESSION', 1 );
if ( isset( $_SERVER['MW_COMPILED'] ) ) {
- require ( 'phase3/includes/WebStart.php' );
+ require ( 'core/includes/WebStart.php' );
} else {
require ( dirname( __FILE__ ) . '/includes/WebStart.php' );
}
'FormAction' => 'includes/Action.php',
'FormOptions' => 'includes/FormOptions.php',
'FormSpecialPage' => 'includes/SpecialPage.php',
+ 'GitInfo' => 'includes/GitInfo.php',
'HashtableReplacer' => 'includes/StringUtils.php',
'HistoryBlob' => 'includes/HistoryBlob.php',
'HistoryBlobCurStub' => 'includes/HistoryBlob.php',
/**
* Randomly hash data while mixing in clock drift data for randomness
*
- * @param $data The data to randomly hash.
+ * @param $data string The data to randomly hash.
* @return String The hashed bytes
* @author Tim Starling
*/
/**
* Return a rolling random state initially build using data from unstable sources
- * @return A new weak random state
+ * @return string A new weak random state
*/
protected function randomState() {
static $state = null;
/**
* Decide on the best acceptable hash algorithm we have available for hash()
+ * @throws MWException
* @return String A hash algorithm
*/
protected function hashAlgo() {
* Generate an acceptably unstable one-way-hash of some text
* making use of the best hash algorithm that we have available.
*
+ * @param $data string
* @return String A raw hash of the data
*/
protected function hash( $data ) {
* Generate an acceptably unstable one-way-hmac of some text
* making use of the best hash algorithm that we have available.
*
+ * @param $data string
+ * @param $key string
* @return String A raw hash of the data
*/
protected function hmac( $data, $key ) {
if ( $iv === false ) {
wfDebug( __METHOD__ . ": mcrypt_create_iv returned false.\n" );
} else {
- $bytes .= $iv;
+ $buffer .= $iv;
wfDebug( __METHOD__ . ": mcrypt_create_iv generated " . strlen( $iv ) . " bytes of randomness.\n" );
}
wfProfileOut( __METHOD__ . '-mcrypt' );
/**
* Return a singleton instance of MWCryptRand
+ * @return MWCryptRand
*/
protected static function singleton() {
if ( is_null( self::$singleton ) ) {
--- /dev/null
+<?php
+/**
+ * A class to help return information about a git repo MediaWiki may be inside
+ * This is used by Special:Version and is also useful for the LocalSettings.php
+ * of anyone working on large branches in git to setup config that show up only
+ * when specific branches are currently checked out.
+ *
+ * @file
+ */
+
+class GitInfo {
+
+ /**
+ * Singleton for the repo at $IP
+ */
+ protected static $repo = null;
+
+ /**
+ * Location of the .git directory
+ */
+ protected $basedir;
+
+ /**
+ * @param $dir The root directory of the repo where the .git dir can be found
+ */
+ public function __construct( $dir ) {
+ $this->basedir = "{$dir}/.git/";
+ }
+
+ /**
+ * Return a singleton for the repo at $IP
+ * @return GitInfo
+ */
+ public static function repo() {
+ global $IP;
+ if ( is_null( self::$repo ) ) {
+ self::$repo = new self( $IP );
+ }
+ return self::$repo;
+ }
+
+ /**
+ * Check if a string looks like a hex encoded SHA1 hash
+ *
+ * @param $str The string to check
+ * @return bool Whether or not the string looks like a SHA1
+ */
+ public static function isSHA1( $str ) {
+ return !!preg_match( '/^[0-9A-Z]{40}$/i', $str );
+ }
+
+ /**
+ * Return the HEAD of the repo (without any opening "ref: ")
+ * @return string The HEAD
+ */
+ public function getHead() {
+ $HEADfile = "{$this->basedir}/HEAD";
+
+ if ( !is_readable( $HEADfile ) ) {
+ return false;
+ }
+
+ $HEAD = file_get_contents( $HEADfile );
+
+ if ( preg_match( "/ref: (.*)/", $HEAD, $m ) ) {
+ return rtrim( $m[1] );
+ } else {
+ return $HEAD;
+ }
+ }
+
+ /**
+ * Return the SHA1 for the current HEAD of the repo
+ * @return string A SHA1 or false
+ */
+ public function getHeadSHA1() {
+ $HEAD = $this->getHead();
+
+ // If detached HEAD may be a SHA1
+ if ( self::isSHA1( $HEAD ) ) {
+ return $HEAD;
+ }
+
+ // If not a SHA1 it may be a ref:
+ $REFfile = "{$this->basedir}{$HEAD}";
+ if ( !is_readable( $REFfile ) ) {
+ return false;
+ }
+
+ $sha1 = rtrim( file_get_contents( $REFfile ) );
+
+ return $sha1;
+ }
+
+ /**
+ * Return the name of the current branch, or HEAD if not found
+ * @return string The branch name, HEAD, or false
+ */
+ public function getCurrentBranch() {
+ $HEAD = $this->getHead();
+ if ( $HEAD && preg_match( "#^refs/heads/(.*)$#", $HEAD, $m ) ) {
+ return $m[1];
+ } else {
+ return $HEAD;
+ }
+ }
+
+ /**
+ * @see self::getHeadSHA1
+ */
+ public static function headSHA1() {
+ return self::repo()->getHeadSHA1();
+ }
+
+ /**
+ * @see self::getCurrentBranch
+ */
+ public static function currentBranch() {
+ return self::repo()->getCurrentBranch();
+ }
+
+}
\ No newline at end of file
$this->gallery->add(
$title,
"$ul<br />\n<i>"
- . htmlspecialchars( $this->getLanguage()->timeanddate( $row->img_timestamp, true ) )
+ . htmlspecialchars( $this->getLanguage()->userTimeAndDate( $row->img_timestamp, $this->getUser() ) )
. "</i><br />\n"
);
}
),
'showbots' => array(
'type' => 'check',
- 'label' => wfMessage( 'showhidebots', wfMsg( 'show' ) ),
+ 'label' => $this->msg( 'showhidebots', $this->msg( 'show' )->plain() )->escaped(),
'name' => 'showbots',
# 'default' => $this->getRequest()->getBool( 'showbots', 0 ),
),
$form = new HTMLForm( $fields, $this->getContext() );
$form->setTitle( $this->getTitle() );
- $form->setSubmitText( wfMsg( 'ilsubmit' ) );
+ $form->setSubmitTextMsg( 'ilsubmit' );
$form->setMethod( 'get' );
- $form->setWrapperLegend( wfMsg( 'newimages-legend' ) );
+ $form->setWrapperLegendMsg( 'newimages-legend' );
return $form;
}
global $wgVersion, $IP;
wfProfileIn( __METHOD__ );
- $info = self::getSvnInfo( $IP );
- if ( !$info ) {
+ $gitInfo = self::getGitHeadSha1( $IP );
+ $svnInfo = self::getSvnInfo( $IP );
+ if ( !$svnInfo && !$gitInfo ) {
$version = $wgVersion;
- } elseif( $flags === 'nodb' ) {
+ } elseif ( $gitInfo ) {
+ $shortSha1 = substr( $gitInfo, 0, 7 );
+ $version = "$wgVersion ($shortSha1)";
+ } elseif ( $flags === 'nodb' ) {
$version = "$wgVersion (r{$info['checkout-rev']})";
} else {
$version = $wgVersion . ' ' .
* @return bool|String sha1 of commit HEAD points to
*/
public static function getGitHeadSha1( $dir ) {
- $BASEDIR = "{$dir}/.git/";
- $HEADfile = "{$BASEDIR}/HEAD";
-
- if( !file_exists( $HEADfile ) ) {
- return false;
- }
-
- preg_match( "/ref: (.*)/",
- file_get_contents( $HEADfile ), $m );
-
- $REFfile = "{$BASEDIR}{$m[1]}";
- if( !file_exists( $REFfile ) ) {
- return false;
- }
-
- $sha1 = rtrim( file_get_contents( $REFfile ) );
-
- return $sha1;
+ $repo = new GitInfo( $dir );
+ return $repo->getHeadSHA1();
}
function showEasterEgg() {
chdir( dirname( dirname( __FILE__ ) ) );
if ( isset( $_SERVER['MW_COMPILED'] ) ) {
- require ( 'phase3/includes/WebStart.php' );
+ require ( 'core/includes/WebStart.php' );
} else {
require( dirname( dirname( __FILE__ ) ) . '/includes/WebStart.php' );
}
$wgEnableProfileInfo = $wgProfileToDatabase = false;
if ( isset( $_SERVER['MW_COMPILED'] ) ) {
- require ( 'phase3/includes/WebStart.php' );
+ require ( 'core/includes/WebStart.php' );
} else {
require ( dirname( __FILE__ ) . '/includes/WebStart.php' );
}
text-align: right;
}
td.timep, td.tpc, td.tpr {
- background-color: #fffff0;
+ background-color: #ffff80;
}
td.memoryp, td.mpc, td.mpr {
- background-color: #f0f8ff;
+ background-color: #80f8ff;
}
td.count, td,cpr {
- background-color: #f0fff0;
+ background-color: #80ff80;
}
td.name {
- background-color: #f9f9f9;
+ background-color: #89f9f9;
+ }
+
+ tr:hover {
+ font-weight: bold;
}
</style>
</head>
*/
( function ( $, mw, undefined ) {
-/**
- * The name of the page to watch or unwatch.
- */
-var title = mw.config.get( 'wgRelevantPageName', mw.config.get( 'wgPageName' ) );
-
-/**
- * Update the link text, link href attribute and (if applicable)
- * "loading" class.
- *
- * @param $link {jQuery} Anchor tag of (un)watch link
- * @param action {String} One of 'watch', 'unwatch'.
- * @param state {String} [optional] 'idle' or 'loading'. Default is 'idle'.
- */
-function updateWatchLink( $link, action, state ) {
- // message keys 'watch', 'watching', 'unwatch' or 'unwatching'.
- var msgKey = state === 'loading' ? action + 'ing' : action,
- accesskeyTip = $link.attr( 'title' ).match( mw.util.tooltipAccessKeyRegexp ),
+ /**
+ * The name of the page to watch or unwatch.
+ */
+ var title = mw.config.get( 'wgRelevantPageName', mw.config.get( 'wgPageName' ) );
+
+ /**
+ * Update the link text, link href attribute and (if applicable)
+ * "loading" class.
+ *
+ * @param $link {jQuery} Anchor tag of (un)watch link.
+ * @param action {String} One of 'watch', 'unwatch'.
+ * @param state {String} [optional] 'idle' or 'loading'. Default is 'idle'.
+ */
+ function updateWatchLink( $link, action, state ) {
+ var accesskeyTip, msgKey, $li;
+
+ // message keys 'watch', 'watching', 'unwatch' or 'unwatching'.
+ msgKey = state === 'loading' ? action + 'ing' : action;
+ accesskeyTip = $link.attr( 'title' ).match( mw.util.tooltipAccessKeyRegexp );
$li = $link.closest( 'li' );
- $link
- .text( mw.msg( msgKey ) )
- .attr( 'title', mw.msg( 'tooltip-ca-' + action ) +
- ( accesskeyTip ? ' ' + accesskeyTip[0] : '' )
- )
- .attr( 'href', mw.util.wikiScript() + '?' + $.param({
- title: title,
- action: action
- })
- );
-
- // Special case for vector icon
- if ( $li.hasClass( 'icon' ) ) {
- if ( state === 'loading' ) {
- $link.addClass( 'loading' );
- } else {
- $link.removeClass( 'loading' );
+ $link
+ .text( mw.msg( msgKey ) )
+ .attr( 'title', mw.msg( 'tooltip-ca-' + action ) +
+ ( accesskeyTip ? ' ' + accesskeyTip[0] : '' )
+ )
+ .attr( 'href', mw.util.wikiScript() + '?' + $.param({
+ title: title,
+ action: action
+ })
+ );
+
+ // Special case for vector icon
+ if ( $li.hasClass( 'icon' ) ) {
+ if ( state === 'loading' ) {
+ $link.addClass( 'loading' );
+ } else {
+ $link.removeClass( 'loading' );
+ }
}
}
-}
-/**
- * @todo This should be moved somewhere more accessible.
- * @param url {String}
- * @return {String} The extracted action, defaults to 'view'.
- */
-function mwUriGetAction( url ) {
- var actionPaths = mw.config.get( 'wgActionPaths' ),
- key, parts, m, action;
-
- // @todo: Does MediaWiki give action path or query param
- // precedence ? If the former, move this to the bottom
- action = mw.util.getParamValue( 'action', url );
- if ( action !== null ) {
- return action;
- }
+ /**
+ * @todo This should be moved somewhere more accessible.
+ * @param url {String}
+ * @return {String} The extracted action, defaults to 'view'.
+ */
+ function mwUriGetAction( url ) {
+ var action, actionPaths, key, i, m, parts;
+
+ actionPaths = mw.config.get( 'wgActionPaths' );
+
+ // @todo: Does MediaWiki give action path or query param
+ // precedence ? If the former, move this to the bottom
+ action = mw.util.getParamValue( 'action', url );
+ if ( action !== null ) {
+ return action;
+ }
+
+ for ( key in actionPaths ) {
+ if ( actionPaths.hasOwnProperty( key ) ) {
+ parts = actionPaths[key].split( '$1' );
+ for ( i = 0; i < parts.length; i += 1 ) {
+ parts[i] = $.escapeRE( parts[i] );
+ }
+ m = new RegExp( parts.join( '(.+)' ) ).exec( url );
+ if ( m && m[1] ) {
+ return key;
+ }
- for ( key in actionPaths ) {
- if ( actionPaths.hasOwnProperty( key ) ) {
- parts = actionPaths[key].split( '$1' );
- for ( i = 0; i < parts.length; i += 1 ) {
- parts[i] = $.escapeRE( parts[i] );
- }
- m = new RegExp( parts.join( '(.+)' ) ).exec( url );
- if ( m && m[1] ) {
- return key;
}
-
}
+
+ return 'view';
}
- return 'view';
-}
+ $( document ).ready( function () {
+ var $links = $( '.mw-watchlink a, a.mw-watchlink, ' +
+ '#ca-watch a, #ca-unwatch a, #mw-unwatch-link1, ' +
+ '#mw-unwatch-link2, #mw-watch-link2, #mw-watch-link1' );
-$( document ).ready( function() {
- var $links = $( '.mw-watchlink a, a.mw-watchlink, ' +
- '#ca-watch a, #ca-unwatch a, #mw-unwatch-link1, ' +
- '#mw-unwatch-link2, #mw-watch-link2, #mw-watch-link1' );
+ // Allowing people to add inline animated links is a little scary
+ $links = $links.filter( ':not( #bodyContent *, #content * )' );
- // Allowing people to add inline animated links is a little scary
- $links = $links.filter( ':not( #bodyContent *, #content * )' );
+ $links.click( function ( e ) {
+ var action, api, $link;
- $links.click( function( e ) {
- var $link, api,
action = mwUriGetAction( this.href );
- if ( action !== 'watch' && action !== 'unwatch' ) {
- // Could not extract target action from link url,
- // let native browsing handle it further
- return true;
- }
- e.preventDefault();
- e.stopPropagation();
-
- $link = $( this );
-
- updateWatchLink( $link, action, 'loading' );
-
- api = new mw.Api();
- api[action](
- title,
- // Success
- function( watchResponse ) {
- var otherAction = action === 'watch' ? 'unwatch' : 'watch',
- $li = $link.closest( 'li' );
+ if ( action !== 'watch' && action !== 'unwatch' ) {
+ // Could not extract target action from link url,
+ // let native browsing handle it further
+ return true;
+ }
+ e.preventDefault();
+ e.stopPropagation();
- mw.util.jsMessage( watchResponse.message, 'ajaxwatch' );
+ $link = $( this );
- // Set link to opposite
- updateWatchLink( $link, otherAction );
+ updateWatchLink( $link, action, 'loading' );
- // Most common ID style
- if ( $li.prop( 'id' ) === 'ca-' + otherAction || $li.prop( 'id' ) === 'ca-' + action ) {
- $li.prop( 'id', 'ca-' + otherAction );
- }
-
- // Bug 12395 - update the watch checkbox on edit pages when the
- // page is watched or unwatched via the tab.
- if ( watchResponse.watched !== undefined ) {
- $( '#wpWatchthis' ).prop( 'checked', true );
- } else {
- $( '#wpWatchthis' ).removeProp( 'checked' );
- }
- },
- // Error
- function(){
-
- // Reset link to non-loading mode
- updateWatchLink( $link, action );
-
- // Format error message
- var cleanTitle = title.replace( /_/g, ' ' );
- var link = mw.html.element(
- 'a', {
- 'href': mw.util.wikiGetlink( title ),
- 'title': cleanTitle
- }, cleanTitle
- );
- var html = mw.msg( 'watcherrortext', link );
-
- // Report to user about the error
- mw.util.jsMessage( html, 'ajaxwatch' );
+ api = new mw.Api();
+ api[action](
+ title,
+ // Success
+ function ( watchResponse ) {
+ var $li, otherAction;
- }
- );
- });
+ otherAction = action === 'watch' ? 'unwatch' : 'watch';
+ $li = $link.closest( 'li' );
-});
+ mw.util.jsMessage( watchResponse.message, 'ajaxwatch' );
+
+ // Set link to opposite
+ updateWatchLink( $link, otherAction );
+
+ // Most common ID style
+ if ( $li.prop( 'id' ) === 'ca-' + otherAction || $li.prop( 'id' ) === 'ca-' + action ) {
+ $li.prop( 'id', 'ca-' + otherAction );
+ }
+
+ // Bug 12395 - update the watch checkbox on edit pages when the
+ // page is watched or unwatched via the tab.
+ if ( watchResponse.watched !== undefined ) {
+ $( '#wpWatchthis' ).prop( 'checked', true );
+ } else {
+ $( '#wpWatchthis' ).removeProp( 'checked' );
+ }
+ },
+ // Error
+ function () {
+ var cleanTitle, html, link;
+
+ // Reset link to non-loading mode
+ updateWatchLink( $link, action );
+
+ // Format error message
+ cleanTitle = title.replace( /_/g, ' ' );
+ link = mw.html.element(
+ 'a', {
+ href: mw.util.wikiGetlink( title ),
+ title: cleanTitle
+ }, cleanTitle
+ );
+ html = mw.msg( 'watcherrortext', link );
+
+ // Report to user about the error
+ mw.util.jsMessage( html, 'ajaxwatch' );
+
+ }
+ );
+ });
+ });
-})( jQuery, mediaWiki );
+}( jQuery, mediaWiki ) );
*/
( function( $, mw ) {
+ /**
+ * @context {mw.Api}
+ */
+ function doWatchInternal( page, success, err, addParams ) {
+ var params = {
+ action: 'watch',
+ title: String( page ),
+ token: mw.user.tokens.get( 'watchToken' ),
+ uselang: mw.config.get( 'wgUserLanguage' )
+ };
+ function ok( data ) {
+ success( data.watch );
+ }
+ if ( addParams ) {
+ $.extend( params, addParams );
+ }
+ return this.post( params, { ok: ok, err: err } );
+ }
+
$.extend( mw.Api.prototype, {
/**
* Convinience method for 'action=watch'.
*
* @param page {String|mw.Title} Full page name or instance of mw.Title
- * @param success {Function} callback to which the watch object will be passed
- * watch object contains 'title' (full page name), 'watched' (boolean) and
+ * @param success {Function} Callback to which the watch object will be passed.
+ * Watch object contains properties 'title' (full pagename), 'watched' (boolean) and
* 'message' (parsed HTML of the 'addedwatchtext' message).
- * @param _unwatch {Boolean} Internally used to re-use this logic for unwatch(),
- * do not use outside this module.
- * @param err {Function} callback if error (optional)
+ * @param err {Function} Error callback (optional)
* @return {jqXHR}
*/
- watch: function( page, success, err, _unwatch ) {
- var params, ok;
- params = {
- action: 'watch',
- title: String( page ),
- token: mw.user.tokens.get( 'watchToken' ),
- uselang: mw.config.get( 'wgUserLanguage' )
- };
- if ( _unwatch ) {
- params.unwatch = 1;
- }
- ok = function( data ) {
- success( data.watch );
- };
- return this.post( params, { ok: ok, err: err } );
+ watch: function ( page, success, err ) {
+ return doWatchInternal.call( this, page, success, err );
},
/**
* Convinience method for 'action=watch&unwatch=1'.
*
* @param page {String|mw.Title} Full page name or instance of mw.Title
- * @param success {Function} callback to which the watch object will be passed
- * watch object contains 'title' (full page name), 'unwatched' (boolean) and
+ * @param success {Function} Callback to which the watch object will be passed.
+ * Watch object contains properties 'title' (full pagename), 'watched' (boolean) and
* 'message' (parsed HTML of the 'removedwatchtext' message).
- * @param err {Function} callback if error (optional)
+ * @param err {Function} Error callback (optional)
* @return {jqXHR}
*/
- unwatch: function( page, success, err ) {
- return this.watch( page, success, err, true );
+ unwatch: function ( page, success, err ) {
+ return doWatchInternal.call( this, page, success, err, { unwatch: 1 } );
}
} );
$nav = $this->data['content_navigation'];
if ( $wgVectorUseIconWatch ) {
- $mode = $this->getSkin()->getTitle()->userIsWatching() ? 'unwatch' : 'watch';
+ $mode = $this->getSkin()->getRelevantTitle()->userIsWatching() ? 'unwatch' : 'watch';
if ( isset( $nav['actions'][$mode] ) ) {
$nav['views'][$mode] = $nav['actions'][$mode];
$nav['views'][$mode]['class'] = rtrim( 'icon ' . $nav['views'][$mode]['class'], ' ' );
<?php
+/**
+ * @group Database
+ */
class RecentChangeTest extends MediaWikiTestCase {
protected $title;
protected $target;
*/
define( 'MW_NO_OUTPUT_COMPRESSION', 1 );
if ( isset( $_SERVER['MW_COMPILED'] ) ) {
- require( 'phase3/includes/WebStart.php' );
+ require( 'core/includes/WebStart.php' );
} else {
require( dirname( __FILE__ ) . '/includes/WebStart.php' );
}