From 63601400e476c6cf43d985f3e7b9864681695ed4 Mon Sep 17 00:00:00 2001 From: Pierre Schmitz Date: Fri, 18 Jan 2013 16:46:04 +0100 Subject: Update to MediaWiki 1.20.2 this update includes: * adjusted Arch Linux skin * updated FluxBBAuthPlugin * patch for https://bugzilla.wikimedia.org/show_bug.cgi?id=44024 --- resources/mediawiki.api/mediawiki.api.category.js | 59 +++++---- resources/mediawiki.api/mediawiki.api.edit.js | 41 +++---- resources/mediawiki.api/mediawiki.api.js | 133 ++++++++++++--------- resources/mediawiki.api/mediawiki.api.parse.js | 45 ++++--- .../mediawiki.api/mediawiki.api.titleblacklist.js | 9 +- resources/mediawiki.api/mediawiki.api.watch.js | 66 +++++----- 6 files changed, 191 insertions(+), 162 deletions(-) (limited to 'resources/mediawiki.api') diff --git a/resources/mediawiki.api/mediawiki.api.category.js b/resources/mediawiki.api/mediawiki.api.category.js index c8c18e69..cc6f704f 100644 --- a/resources/mediawiki.api/mediawiki.api.category.js +++ b/resources/mediawiki.api/mediawiki.api.category.js @@ -1,8 +1,7 @@ /** * Additional mw.Api methods to assist with API calls related to categories. */ - -( function( $, mw, undefined ) { +( function ( mw, $ ) { $.extend( mw.Api.prototype, { /** @@ -12,22 +11,23 @@ * @param err {Function} optional callback to run if api error * @return ajax call object */ - isCategory: function( title, success, err ) { - var params = { - prop: 'categoryinfo', - titles: title.toString() - }, - ok = function( data ) { - var exists = false; - if ( data.query && data.query.pages ) { - $.each( data.query.pages, function( id, page ) { - if ( page.categoryinfo ) { - exists = true; - } - } ); - } - success( exists ); - }; + isCategory: function ( title, success, err ) { + var params, ok; + params = { + prop: 'categoryinfo', + titles: title.toString() + }; + ok = function ( data ) { + var exists = false; + if ( data.query && data.query.pages ) { + $.each( data.query.pages, function ( id, page ) { + if ( page.categoryinfo ) { + exists = true; + } + } ); + } + success( exists ); + }; return this.get( params, { ok: ok, err: err } ); }, @@ -40,19 +40,18 @@ * @param err {Function} optional callback to run if api error * @return {jqXHR} */ - getCategoriesByPrefix: function( prefix, success, err ) { - - // fetch with allpages to only get categories that have a corresponding description page. - var params = { + getCategoriesByPrefix: function ( prefix, success, err ) { + // Fetch with allpages to only get categories that have a corresponding description page. + var params, ok; + params = { 'list': 'allpages', 'apprefix': prefix, 'apnamespace': mw.config.get('wgNamespaceIds').category }; - - var ok = function( data ) { + ok = function ( data ) { var texts = []; if ( data.query && data.query.allpages ) { - $.each( data.query.allpages, function( i, category ) { + $.each( data.query.allpages, function ( i, category ) { texts.push( new mw.Title( category.title ).getNameText() ); } ); } @@ -71,7 +70,7 @@ * @param async {Boolean} optional asynchronousness (default = true = async) * @return {jqXHR} */ - getCategories: function( title, success, err, async ) { + getCategories: function ( title, success, err, async ) { var params, ok; params = { prop: 'categories', @@ -80,15 +79,15 @@ if ( async === undefined ) { async = true; } - ok = function( data ) { + ok = function ( data ) { var ret = false; if ( data.query && data.query.pages ) { - $.each( data.query.pages, function( id, page ) { + $.each( data.query.pages, function ( id, page ) { if ( page.categories ) { if ( typeof ret !== 'object' ) { ret = []; } - $.each( page.categories, function( i, cat ) { + $.each( page.categories, function ( i, cat ) { ret.push( new mw.Title( cat.title ) ); } ); } @@ -102,4 +101,4 @@ } ); -} )( jQuery, mediaWiki ); +}( mediaWiki, jQuery ) ); diff --git a/resources/mediawiki.api/mediawiki.api.edit.js b/resources/mediawiki.api/mediawiki.api.edit.js index a9d488a8..49af9375 100644 --- a/resources/mediawiki.api/mediawiki.api.edit.js +++ b/resources/mediawiki.api/mediawiki.api.edit.js @@ -1,8 +1,7 @@ /** * Additional mw.Api methods to assist with API calls related to editing wiki pages. */ - -( function( $, mw, undefined ) { +( function ( mw, $ ) { // Cache token so we don't have to keep fetching new ones for every single request. var cachedToken = null; @@ -19,13 +18,14 @@ * @param err {Function} [optional] error callback * @return {jqXHR} */ - postWithEditToken: function( params, ok, err ) { - var api = this, useTokenToPost, getTokenIfBad; + postWithEditToken: function ( params, ok, err ) { + var useTokenToPost, getTokenIfBad, + api = this; if ( cachedToken === null ) { // We don't have a valid cached token, so get a fresh one and try posting. // We do not trap any 'badtoken' or 'notoken' errors, because we don't want // an infinite loop. If this fresh token is bad, something else is very wrong. - useTokenToPost = function( token ) { + useTokenToPost = function ( token ) { params.token = token; api.post( params, ok, err ); }; @@ -34,9 +34,10 @@ // We do have a token, but it might be expired. So if it is 'bad' then // start over with a new token. params.token = cachedToken; - getTokenIfBad = function( code, result ) { + getTokenIfBad = function ( code, result ) { if ( code === 'badtoken' ) { - cachedToken = null; // force a new token + // force a new token, clear any old one + cachedToken = null; api.postWithEditToken( params, ok, err ); } else { err( code, result ); @@ -58,23 +59,17 @@ * @param err {Function} error callback * @return {jqXHR} */ - getEditToken: function( tokenCallback, err ) { + getEditToken: function ( tokenCallback, err ) { var parameters = { - prop: 'info', - intoken: 'edit', - // we need some kind of dummy page to get a token from. This will return a response - // complaining that the page is missing, but we should also get an edit token - titles: 'DummyPageForEditToken' + action: 'tokens', + type: 'edit' }, - ok = function( data ) { + ok = function ( data ) { var token; - $.each( data.query.pages, function( i, page ) { - if ( page.edittoken ) { - token = page.edittoken; - return false; - } - } ); - if ( token !== undefined ) { + // If token type is not available for this user, + // key 'edittoken' is missing or can contain Boolean false + if ( data.tokens && data.tokens.edittoken ) { + token = data.tokens.edittoken; cachedToken = token; tokenCallback( token ); } else { @@ -102,7 +97,7 @@ * @param err {Function} error handler * @return {jqXHR} */ - newSection: function( title, header, message, ok, err ) { + newSection: function ( title, header, message, ok, err ) { var params = { action: 'edit', section: 'new', @@ -116,4 +111,4 @@ } ); -} )( jQuery, mediaWiki ); +}( mediaWiki, jQuery ) ); diff --git a/resources/mediawiki.api/mediawiki.api.js b/resources/mediawiki.api/mediawiki.api.js index 225093b3..a184e3ca 100644 --- a/resources/mediawiki.api/mediawiki.api.js +++ b/resources/mediawiki.api/mediawiki.api.js @@ -1,6 +1,7 @@ -/* mw.Api objects represent the API of a particular MediaWiki server. */ - -( function( $, mw, undefined ) { +/** + * mw.Api objects represent the API of a particular MediaWiki server. + */ +( function ( mw, $ ) { /** * @var defaultOptions {Object} @@ -21,14 +22,7 @@ ajax: { url: mw.util.wikiScript( 'api' ), - ok: function() {}, - - // caller can supply handlers for http transport error or api errors - err: function( code, result ) { - mw.log( 'mw.Api error: ' + code, 'debug' ); - }, - - timeout: 30000, // 30 seconds + timeout: 30 * 1000, // 30 seconds dataType: 'json' } @@ -53,7 +47,7 @@ * @param options {Object} See defaultOptions documentation above. Ajax options can also be * overridden for each individual request to jQuery.ajax() later on. */ - mw.Api = function( options ) { + mw.Api = function ( options ) { if ( options === undefined ) { options = {}; @@ -73,34 +67,31 @@ mw.Api.prototype = { /** - * For api queries, in simple cases the caller just passes a success callback. - * In complex cases they pass an object with a success property as callback and - * probably other options. - * Normalize the argument so that it's always the latter case. + * Normalize the ajax options for compatibility and/or convenience methods. * - * @param {Object|Function} An object contaning one or more of options.ajax, + * @param {undefined|Object|Function} An object contaning one or more of options.ajax, * or just a success function (options.ajax.ok). * @return {Object} Normalized ajax options. */ - normalizeAjaxOptions: function( arg ) { - var opt = arg; + normalizeAjaxOptions: function ( arg ) { + // Arg argument is usually empty + // (before MW 1.20 it was often used to pass ok/err callbacks) + var opts = arg || {}; + // Options can also be a success callback handler if ( typeof arg === 'function' ) { - opt = { 'ok': arg }; + opts = { ok: arg }; } - if ( !opt.ok ) { - throw new Error( 'ajax options must include ok callback' ); - } - return opt; + return opts; }, /** * Perform API get request * * @param {Object} request parameters - * @param {Object|Function} ajax options, or just a success function - * @return {jqXHR} + * @param {Object|Function} [optional] ajax options + * @return {jQuery.Promise} */ - get: function( parameters, ajaxOptions ) { + get: function ( parameters, ajaxOptions ) { ajaxOptions = this.normalizeAjaxOptions( ajaxOptions ); ajaxOptions.type = 'GET'; return this.ajax( parameters, ajaxOptions ); @@ -111,10 +102,10 @@ * @todo Post actions for nonlocal will need proxy * * @param {Object} request parameters - * @param {Object|Function} ajax options, or just a success function - * @return {jqXHR} + * @param {Object|Function} [optional] ajax options + * @return {jQuery.Promise} */ - post: function( parameters, ajaxOptions ) { + post: function ( parameters, ajaxOptions ) { ajaxOptions = this.normalizeAjaxOptions( ajaxOptions ); ajaxOptions.type = 'POST'; return this.ajax( parameters, ajaxOptions ); @@ -125,39 +116,72 @@ * * @param {Object} request parameters * @param {Object} ajax options - * @return {jqXHR} + * @return {jQuery.Promise} + * - done: API response data as first argument + * - fail: errorcode as first arg, details (string or object) as second arg. */ - ajax: function( parameters, ajaxOptions ) { + ajax: function ( parameters, ajaxOptions ) { + var token, + apiDeferred = $.Deferred(); + parameters = $.extend( {}, this.defaults.parameters, parameters ); ajaxOptions = $.extend( {}, this.defaults.ajax, ajaxOptions ); + // Ensure that token parameter is last (per [[mw:API:Edit#Token]]). + if ( parameters.token ) { + token = parameters.token; + delete parameters.token; + } // Some deployed MediaWiki >= 1.17 forbid periods in URLs, due to an IE XSS bug // So let's escape them here. See bug #28235 // This works because jQuery accepts data as a query string or as an Object ajaxOptions.data = $.param( parameters ).replace( /\./g, '%2E' ); - ajaxOptions.error = function( xhr, textStatus, exception ) { - ajaxOptions.err( 'http', { - xhr: xhr, - textStatus: textStatus, - exception: exception + // If we extracted a token parameter, add it back in. + if ( token ) { + ajaxOptions.data += '&token=' + encodeURIComponent( token ); + } + + // Backwards compatibility: Before MediaWiki 1.20, + // callbacks were done with the 'ok' and 'err' property in ajaxOptions. + if ( ajaxOptions.ok ) { + apiDeferred.done( ajaxOptions.ok ); + delete ajaxOptions.ok; + } + if ( ajaxOptions.err ) { + apiDeferred.fail( ajaxOptions.err ); + delete ajaxOptions.err; + } + + // Make the AJAX request + $.ajax( ajaxOptions ) + // If AJAX fails, reject API call with error code 'http' + // and details in second argument. + .fail( function ( xhr, textStatus, exception ) { + apiDeferred.reject( 'http', { + xhr: xhr, + textStatus: textStatus, + exception: exception + } ); + } ) + // AJAX success just means "200 OK" response, also check API error codes + .done( function ( result ) { + if ( result === undefined || result === null || result === '' ) { + apiDeferred.reject( 'ok-but-empty', + 'OK response but empty result (check HTTP headers?)' + ); + } else if ( result.error ) { + var code = result.error.code === undefined ? 'unknown' : result.error.code; + apiDeferred.reject( code, result ); + } else { + apiDeferred.resolve( result ); + } } ); - }; - - // Success just means 200 OK; also check for output and API errors - ajaxOptions.success = function( result ) { - if ( result === undefined || result === null || result === '' ) { - ajaxOptions.err( 'ok-but-empty', - 'OK response but empty result (check HTTP headers?)' ); - } else if ( result.error ) { - var code = result.error.code === undefined ? 'unknown' : result.error.code; - ajaxOptions.err( code, result ); - } else { - ajaxOptions.ok( result ); - } - }; - - return $.ajax( ajaxOptions ); + + // Return the Promise + return apiDeferred.promise().fail( function ( code, details ) { + mw.log( 'mw.Api error: ', code, details ); + }); } }; @@ -197,6 +221,7 @@ 'file-too-large', 'filetype-missing', 'filetype-banned', + 'filetype-banned-type', 'filename-tooshort', 'illegal-filename', 'verification-error', @@ -221,4 +246,4 @@ 'exists' ]; -})( jQuery, mediaWiki ); +}( mediaWiki, jQuery ) ); diff --git a/resources/mediawiki.api/mediawiki.api.parse.js b/resources/mediawiki.api/mediawiki.api.parse.js index 1cc68f29..e8d1b3e6 100644 --- a/resources/mediawiki.api/mediawiki.api.parse.js +++ b/resources/mediawiki.api/mediawiki.api.parse.js @@ -1,31 +1,42 @@ /** - * Additional mw.Api methods to assist with API calls related to parsing wikitext. + * mw.Api methods for parsing wikitext. */ - -( function( $, mw ) { +( function ( mw, $ ) { $.extend( mw.Api.prototype, { /** * Convinience method for 'action=parse'. Parses wikitext into HTML. * * @param wikiText {String} - * @param success {Function} callback to which to pass success HTML - * @param err {Function} callback if error (optional) - * @return {jqXHR} + * @param ok {Function} [optional] deprecated (success callback) + * @param err {Function} [optional] deprecated (error callback) + * @return {jQuery.Promise} */ - parse: function( wikiText, success, err ) { - var params = { - text: wikiText, - action: 'parse' - }, - ok = function( data ) { + parse: function ( wikiText, ok, err ) { + var apiDeferred = $.Deferred(); + + // Backwards compatibility (< MW 1.20) + if ( ok ) { + apiDeferred.done( ok ); + } + if ( err ) { + apiDeferred.fail( err ); + } + + this.get( { + action: 'parse', + text: wikiText + } ) + .done( function ( data ) { if ( data.parse && data.parse.text && data.parse.text['*'] ) { - success( data.parse.text['*'] ); + apiDeferred.resolve( data.parse.text['*'] ); } - }; - return this.get( params, { ok: ok, err: err } ); - } + } ) + .fail( apiDeferred.reject ); + // Return the promise + return apiDeferred.promise(); + } } ); -} )( jQuery, mediaWiki ); +}( mediaWiki, jQuery ) ); diff --git a/resources/mediawiki.api/mediawiki.api.titleblacklist.js b/resources/mediawiki.api/mediawiki.api.titleblacklist.js index 5435945b..1f7e275a 100644 --- a/resources/mediawiki.api/mediawiki.api.titleblacklist.js +++ b/resources/mediawiki.api/mediawiki.api.titleblacklist.js @@ -2,7 +2,7 @@ * Additional mw.Api methods to assist with API calls to the API module of the TitleBlacklist extension. */ -( function( $, mw, undefined ) { +( function ( mw, $ ) { $.extend( mw.Api.prototype, { /** @@ -15,13 +15,13 @@ * @param err {Function} optional callback to run if api error * @return {jqXHR} */ - isBlacklisted: function( title, success, err ) { + isBlacklisted: function ( title, success, err ) { var params = { action: 'titleblacklist', tbaction: 'create', tbtitle: title.toString() }, - ok = function( data ) { + ok = function ( data ) { var result; // this fails open (if nothing valid is returned by the api, allows the title) @@ -48,4 +48,5 @@ } } ); -} )( jQuery, mediaWiki ); + +}( mediaWiki, jQuery ) ); diff --git a/resources/mediawiki.api/mediawiki.api.watch.js b/resources/mediawiki.api/mediawiki.api.watch.js index 3f2525ad..d3234421 100644 --- a/resources/mediawiki.api/mediawiki.api.watch.js +++ b/resources/mediawiki.api/mediawiki.api.watch.js @@ -2,57 +2,55 @@ * Additional mw.Api methods to assist with (un)watching wiki pages. * @since 1.19 */ -( function( $, mw ) { +( 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 err {Function} callback if error (optional) + * @param err {Function} Error callback (optional) * @return {jqXHR} */ - watch: function( page, success, err ) { - var params, ok; - params = { - action: 'watch', - title: String( page ), - token: mw.user.tokens.get( 'watchToken' ), - uselang: mw.config.get( 'wgUserLanguage' ) - }; - 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='. + * 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 ) { - var params, ok; - params = { - action: 'watch', - unwatch: 1, - title: String( page ), - token: mw.user.tokens.get( 'watchToken' ), - uselang: mw.config.get( 'wgUserLanguage' ) - }; - ok = function( data ) { - success( data.watch ); - }; - return this.post( params, { ok: ok, err: err } ); + unwatch: function ( page, success, err ) { + return doWatchInternal.call( this, page, success, err, { unwatch: 1 } ); } } ); -} )( jQuery, mediaWiki ); +}( mediaWiki, jQuery ) ); -- cgit v1.2.2