diff options
Diffstat (limited to 'resources/mediawiki.api/mediawiki.api.js')
-rw-r--r-- | resources/mediawiki.api/mediawiki.api.js | 133 |
1 files changed, 79 insertions, 54 deletions
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 ) ); |