From: Sam Reed Date: Mon, 6 Feb 2012 16:58:10 +0000 (+0000) Subject: Move mediawiki.api to own folder X-Git-Tag: 1.31.0-rc.0~24915 X-Git-Url: http://git.cyclocoop.org/%7B%24www_url%7Dadmin/compta/operations/?a=commitdiff_plain;h=82ad85f2e258fd5a359c221dec8630a46da4d97d;p=lhc%2Fweb%2Fwiklou.git Move mediawiki.api to own folder --- diff --git a/resources/Resources.php b/resources/Resources.php index 1cdd275aaf..ff24031938 100644 --- a/resources/Resources.php +++ b/resources/Resources.php @@ -506,36 +506,36 @@ return array( 'debugRaw' => false, ), 'mediawiki.api' => array( - 'scripts' => 'resources/mediawiki/mediawiki.api.js', + 'scripts' => 'resources/mediawiki/mediawiki.api/mediawiki.api.js', 'dependencies' => 'mediawiki.util', ), 'mediawiki.api.category' => array( - 'scripts' => 'resources/mediawiki/mediawiki.api.category.js', + 'scripts' => 'resources/mediawiki/mediawiki.api/mediawiki.api.category.js', 'dependencies' => array( 'mediawiki.api', 'mediawiki.Title' ), ), 'mediawiki.api.edit' => array( - 'scripts' => 'resources/mediawiki/mediawiki.api.edit.js', + 'scripts' => 'resources/mediawiki/mediawiki.api/mediawiki.api.edit.js', 'dependencies' => array( 'mediawiki.api', 'mediawiki.Title' ), ), 'mediawiki.api.parse' => array( - 'scripts' => 'resources/mediawiki/mediawiki.api.parse.js', + 'scripts' => 'resources/mediawiki/mediawiki.api/mediawiki.api.parse.js', 'dependencies' => 'mediawiki.api', ), 'mediawiki.api.titleblacklist' => array( - 'scripts' => 'resources/mediawiki/mediawiki.api.titleblacklist.js', + 'scripts' => 'resources/mediawiki/mediawiki.api/mediawiki.api.titleblacklist.js', 'dependencies' => array( 'mediawiki.api', 'mediawiki.Title' ), ), 'mediawiki.api.watch' => array( - 'scripts' => 'resources/mediawiki/mediawiki.api.watch.js', + 'scripts' => 'resources/mediawiki/mediawiki.api/mediawiki.api.watch.js', 'dependencies' => 'mediawiki.api', ), 'mediawiki.debug' => array( diff --git a/resources/mediawiki.api/mediawiki.api.category.js b/resources/mediawiki.api/mediawiki.api.category.js new file mode 100644 index 0000000000..c8c18e69fa --- /dev/null +++ b/resources/mediawiki.api/mediawiki.api.category.js @@ -0,0 +1,105 @@ +/** + * Additional mw.Api methods to assist with API calls related to categories. + */ + +( function( $, mw, undefined ) { + + $.extend( mw.Api.prototype, { + /** + * Determine if a category exists. + * @param title {mw.Title} + * @param success {Function} callback to pass boolean of category's existence + * @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 ); + }; + + return this.get( params, { ok: ok, err: err } ); + }, + + /** + * Get a list of categories that match a certain prefix. + * e.g. given "Foo", return "Food", "Foolish people", "Foosball tables" ... + * @param prefix {String} prefix to match + * @param success {Function} callback to pass matched categories to + * @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 = { + 'list': 'allpages', + 'apprefix': prefix, + 'apnamespace': mw.config.get('wgNamespaceIds').category + }; + + var ok = function( data ) { + var texts = []; + if ( data.query && data.query.allpages ) { + $.each( data.query.allpages, function( i, category ) { + texts.push( new mw.Title( category.title ).getNameText() ); + } ); + } + success( texts ); + }; + + return this.get( params, { ok: ok, err: err } ); + }, + + + /** + * Get the categories that a particular page on the wiki belongs to + * @param title {mw.Title} + * @param success {Function} callback to pass categories to (or false, if title not found) + * @param err {Function} optional callback to run if api error + * @param async {Boolean} optional asynchronousness (default = true = async) + * @return {jqXHR} + */ + getCategories: function( title, success, err, async ) { + var params, ok; + params = { + prop: 'categories', + titles: title.toString() + }; + if ( async === undefined ) { + async = true; + } + ok = function( data ) { + var ret = false; + if ( data.query && data.query.pages ) { + $.each( data.query.pages, function( id, page ) { + if ( page.categories ) { + if ( typeof ret !== 'object' ) { + ret = []; + } + $.each( page.categories, function( i, cat ) { + ret.push( new mw.Title( cat.title ) ); + } ); + } + } ); + } + success( ret ); + }; + + return this.get( params, { ok: ok, err: err, async: async } ); + } + + } ); + +} )( jQuery, mediaWiki ); diff --git a/resources/mediawiki.api/mediawiki.api.edit.js b/resources/mediawiki.api/mediawiki.api.edit.js new file mode 100644 index 0000000000..a9d488a832 --- /dev/null +++ b/resources/mediawiki.api/mediawiki.api.edit.js @@ -0,0 +1,119 @@ +/** + * Additional mw.Api methods to assist with API calls related to editing wiki pages. + */ + +( function( $, mw, undefined ) { + + // Cache token so we don't have to keep fetching new ones for every single request. + var cachedToken = null; + + $.extend( mw.Api.prototype, { + + /** + * Post to API with edit token. If we have no token, get one and try to post. + * If we have a cached token try using that, and if it fails, blank out the + * cached token and start over. + * + * @param params {Object} API parameters + * @param ok {Function} callback for success + * @param err {Function} [optional] error callback + * @return {jqXHR} + */ + postWithEditToken: function( params, ok, err ) { + var api = this, useTokenToPost, getTokenIfBad; + 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 ) { + params.token = token; + api.post( params, ok, err ); + }; + return api.getEditToken( useTokenToPost, err ); + } else { + // 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 ) { + if ( code === 'badtoken' ) { + cachedToken = null; // force a new token + api.postWithEditToken( params, ok, err ); + } else { + err( code, result ); + } + }; + return api.post( params, { ok : ok, err : getTokenIfBad }); + } + }, + + /** + * Api helper to grab an edit token + * + * token callback has signature ( String token ) + * error callback has signature ( String code, Object results, XmlHttpRequest xhr, Exception exception ) + * Note that xhr and exception are only available for 'http_*' errors + * code may be any http_* error code (see mw.Api), or 'token_missing' + * + * @param tokenCallback {Function} received token callback + * @param err {Function} error callback + * @return {jqXHR} + */ + 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' + }, + ok = function( data ) { + var token; + $.each( data.query.pages, function( i, page ) { + if ( page.edittoken ) { + token = page.edittoken; + return false; + } + } ); + if ( token !== undefined ) { + cachedToken = token; + tokenCallback( token ); + } else { + err( 'token-missing', data ); + } + }, + ajaxOptions = { + ok: ok, + err: err, + // Due to the API assuming we're logged out if we pass the callback-parameter, + // we have to disable jQuery's callback system, and instead parse JSON string, + // by setting 'jsonp' to false. + jsonp: false + }; + + return this.get( parameters, ajaxOptions ); + }, + + /** + * Create a new section of the page. + * @param title {mw.Title|String} target page + * @param header {String} + * @param message {String} wikitext message + * @param ok {Function} success handler + * @param err {Function} error handler + * @return {jqXHR} + */ + newSection: function( title, header, message, ok, err ) { + var params = { + action: 'edit', + section: 'new', + format: 'json', + title: title.toString(), + summary: header, + text: message + }; + return this.postWithEditToken( params, ok, err ); + } + + } ); + +} )( jQuery, mediaWiki ); diff --git a/resources/mediawiki.api/mediawiki.api.js b/resources/mediawiki.api/mediawiki.api.js new file mode 100644 index 0000000000..225093b36b --- /dev/null +++ b/resources/mediawiki.api/mediawiki.api.js @@ -0,0 +1,224 @@ +/* mw.Api objects represent the API of a particular MediaWiki server. */ + +( function( $, mw, undefined ) { + + /** + * @var defaultOptions {Object} + * We allow people to omit these default parameters from API requests + * there is very customizable error handling here, on a per-call basis + * wondering, would it be simpler to make it easy to clone the api object, + * change error handling, and use that instead? + */ + var defaultOptions = { + + // Query parameters for API requests + parameters: { + action: 'query', + format: 'json' + }, + + // Ajax options for jQuery.ajax() + 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 + + dataType: 'json' + } + }; + + /** + * Constructor to create an object to interact with the API of a particular MediaWiki server. + * + * @todo Share API objects with exact same config. + * @example + * + * var api = new mw.Api(); + * api.get( { + * action: 'query', + * meta: 'userinfo' + * }, { + * ok: function () { console.log( arguments ); } + * } ); + * + * + * @constructor + * @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 ) { + + if ( options === undefined ) { + options = {}; + } + + // Force toString if we got a mw.Uri object + if ( options.ajax && options.ajax.url !== undefined ) { + options.ajax.url = String( options.ajax.url ); + } + + options.parameters = $.extend( {}, defaultOptions.parameters, options.parameters ); + options.ajax = $.extend( {}, defaultOptions.ajax, options.ajax ); + + this.defaults = options; + }; + + 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. + * + * @param {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; + if ( typeof arg === 'function' ) { + opt = { 'ok': arg }; + } + if ( !opt.ok ) { + throw new Error( 'ajax options must include ok callback' ); + } + return opt; + }, + + /** + * Perform API get request + * + * @param {Object} request parameters + * @param {Object|Function} ajax options, or just a success function + * @return {jqXHR} + */ + get: function( parameters, ajaxOptions ) { + ajaxOptions = this.normalizeAjaxOptions( ajaxOptions ); + ajaxOptions.type = 'GET'; + return this.ajax( parameters, ajaxOptions ); + }, + + /** + * Perform API post request + * @todo Post actions for nonlocal will need proxy + * + * @param {Object} request parameters + * @param {Object|Function} ajax options, or just a success function + * @return {jqXHR} + */ + post: function( parameters, ajaxOptions ) { + ajaxOptions = this.normalizeAjaxOptions( ajaxOptions ); + ajaxOptions.type = 'POST'; + return this.ajax( parameters, ajaxOptions ); + }, + + /** + * Perform the API call. + * + * @param {Object} request parameters + * @param {Object} ajax options + * @return {jqXHR} + */ + ajax: function( parameters, ajaxOptions ) { + parameters = $.extend( {}, this.defaults.parameters, parameters ); + ajaxOptions = $.extend( {}, this.defaults.ajax, ajaxOptions ); + + // 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 + } ); + }; + + // 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 ); + } + + }; + + /** + * @var {Array} List of errors we might receive from the API. + * For now, this just documents our expectation that there should be similar messages + * available. + */ + mw.Api.errors = [ + // occurs when POST aborted + // jQuery 1.4 can't distinguish abort or lost connection from 200 OK + empty result + 'ok-but-empty', + + // timeout + 'timeout', + + // really a warning, but we treat it like an error + 'duplicate', + 'duplicate-archive', + + // upload succeeded, but no image info. + // this is probably impossible, but might as well check for it + 'noimageinfo', + // remote errors, defined in API + 'uploaddisabled', + 'nomodule', + 'mustbeposted', + 'badaccess-groups', + 'stashfailed', + 'missingresult', + 'missingparam', + 'invalid-file-key', + 'copyuploaddisabled', + 'mustbeloggedin', + 'empty-file', + 'file-too-large', + 'filetype-missing', + 'filetype-banned', + 'filename-tooshort', + 'illegal-filename', + 'verification-error', + 'hookaborted', + 'unknown-error', + 'internal-error', + 'overwrite', + 'badtoken', + 'fetchfileerror', + 'fileexists-shared-forbidden', + 'invalidtitle', + 'notloggedin' + ]; + + /** + * @var {Array} List of warnings we might receive from the API. + * For now, this just documents our expectation that there should be similar messages + * available. + */ + mw.Api.warnings = [ + 'duplicate', + 'exists' + ]; + +})( jQuery, mediaWiki ); diff --git a/resources/mediawiki.api/mediawiki.api.parse.js b/resources/mediawiki.api/mediawiki.api.parse.js new file mode 100644 index 0000000000..1cc68f29cf --- /dev/null +++ b/resources/mediawiki.api/mediawiki.api.parse.js @@ -0,0 +1,31 @@ +/** + * Additional mw.Api methods to assist with API calls related to parsing wikitext. + */ + +( 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} + */ + parse: function( wikiText, success, err ) { + var params = { + text: wikiText, + action: 'parse' + }, + ok = function( data ) { + if ( data.parse && data.parse.text && data.parse.text['*'] ) { + success( data.parse.text['*'] ); + } + }; + return this.get( params, { ok: ok, err: err } ); + } + + } ); + +} )( jQuery, mediaWiki ); diff --git a/resources/mediawiki.api/mediawiki.api.titleblacklist.js b/resources/mediawiki.api/mediawiki.api.titleblacklist.js new file mode 100644 index 0000000000..5435945b60 --- /dev/null +++ b/resources/mediawiki.api/mediawiki.api.titleblacklist.js @@ -0,0 +1,51 @@ +/** + * Additional mw.Api methods to assist with API calls to the API module of the TitleBlacklist extension. + */ + +( function( $, mw, undefined ) { + + $.extend( mw.Api.prototype, { + /** + * Convinience method for 'action=titleblacklist'. + * Note: This action is not provided by MediaWiki core, but as part of the TitleBlacklist extension. + * + * @param title {mw.Title} + * @param success {Function} Called on successfull request. First argument is false if title wasn't blacklisted, + * object with 'reason', 'line' and 'message' properties if title was blacklisted. + * @param err {Function} optional callback to run if api error + * @return {jqXHR} + */ + isBlacklisted: function( title, success, err ) { + var params = { + action: 'titleblacklist', + tbaction: 'create', + tbtitle: title.toString() + }, + ok = function( data ) { + var result; + + // this fails open (if nothing valid is returned by the api, allows the title) + // also fails open when the API is not present, which will be most of the time + // as this API module is part of the TitleBlacklist extension. + if ( data.titleblacklist && data.titleblacklist.result && data.titleblacklist.result === 'blacklisted') { + if ( data.titleblacklist.reason ) { + result = { + reason: data.titleblacklist.reason, + line: data.titleblacklist.line, + message: data.titleblacklist.message + }; + } else { + mw.log('mw.Api.titleblacklist::isBlacklisted> no reason data for blacklisted title', 'debug'); + result = { reason: 'Blacklisted, but no reason supplied', line: 'Unknown', message: null }; + } + success( result ); + } else { + success ( false ); + } + }; + + return this.get( params, { ok: ok, err: err } ); + } + + } ); +} )( jQuery, mediaWiki ); diff --git a/resources/mediawiki.api/mediawiki.api.watch.js b/resources/mediawiki.api/mediawiki.api.watch.js new file mode 100644 index 0000000000..3f2525ad30 --- /dev/null +++ b/resources/mediawiki.api/mediawiki.api.watch.js @@ -0,0 +1,58 @@ +/** + * Additional mw.Api methods to assist with (un)watching wiki pages. + * @since 1.19 + */ +( function( $, mw ) { + + $.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 + * 'message' (parsed HTML of the 'addedwatchtext' message). + * @param err {Function} callback if error (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 } ); + }, + /** + * Convinience method for 'action=watch&unwatch='. + * + * @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 + * 'message' (parsed HTML of the 'removedwatchtext' message). + * @param err {Function} callback if error (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 } ); + } + + } ); + +} )( jQuery, mediaWiki ); diff --git a/resources/mediawiki/mediawiki.api.category.js b/resources/mediawiki/mediawiki.api.category.js deleted file mode 100644 index c8c18e69fa..0000000000 --- a/resources/mediawiki/mediawiki.api.category.js +++ /dev/null @@ -1,105 +0,0 @@ -/** - * Additional mw.Api methods to assist with API calls related to categories. - */ - -( function( $, mw, undefined ) { - - $.extend( mw.Api.prototype, { - /** - * Determine if a category exists. - * @param title {mw.Title} - * @param success {Function} callback to pass boolean of category's existence - * @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 ); - }; - - return this.get( params, { ok: ok, err: err } ); - }, - - /** - * Get a list of categories that match a certain prefix. - * e.g. given "Foo", return "Food", "Foolish people", "Foosball tables" ... - * @param prefix {String} prefix to match - * @param success {Function} callback to pass matched categories to - * @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 = { - 'list': 'allpages', - 'apprefix': prefix, - 'apnamespace': mw.config.get('wgNamespaceIds').category - }; - - var ok = function( data ) { - var texts = []; - if ( data.query && data.query.allpages ) { - $.each( data.query.allpages, function( i, category ) { - texts.push( new mw.Title( category.title ).getNameText() ); - } ); - } - success( texts ); - }; - - return this.get( params, { ok: ok, err: err } ); - }, - - - /** - * Get the categories that a particular page on the wiki belongs to - * @param title {mw.Title} - * @param success {Function} callback to pass categories to (or false, if title not found) - * @param err {Function} optional callback to run if api error - * @param async {Boolean} optional asynchronousness (default = true = async) - * @return {jqXHR} - */ - getCategories: function( title, success, err, async ) { - var params, ok; - params = { - prop: 'categories', - titles: title.toString() - }; - if ( async === undefined ) { - async = true; - } - ok = function( data ) { - var ret = false; - if ( data.query && data.query.pages ) { - $.each( data.query.pages, function( id, page ) { - if ( page.categories ) { - if ( typeof ret !== 'object' ) { - ret = []; - } - $.each( page.categories, function( i, cat ) { - ret.push( new mw.Title( cat.title ) ); - } ); - } - } ); - } - success( ret ); - }; - - return this.get( params, { ok: ok, err: err, async: async } ); - } - - } ); - -} )( jQuery, mediaWiki ); diff --git a/resources/mediawiki/mediawiki.api.edit.js b/resources/mediawiki/mediawiki.api.edit.js deleted file mode 100644 index a9d488a832..0000000000 --- a/resources/mediawiki/mediawiki.api.edit.js +++ /dev/null @@ -1,119 +0,0 @@ -/** - * Additional mw.Api methods to assist with API calls related to editing wiki pages. - */ - -( function( $, mw, undefined ) { - - // Cache token so we don't have to keep fetching new ones for every single request. - var cachedToken = null; - - $.extend( mw.Api.prototype, { - - /** - * Post to API with edit token. If we have no token, get one and try to post. - * If we have a cached token try using that, and if it fails, blank out the - * cached token and start over. - * - * @param params {Object} API parameters - * @param ok {Function} callback for success - * @param err {Function} [optional] error callback - * @return {jqXHR} - */ - postWithEditToken: function( params, ok, err ) { - var api = this, useTokenToPost, getTokenIfBad; - 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 ) { - params.token = token; - api.post( params, ok, err ); - }; - return api.getEditToken( useTokenToPost, err ); - } else { - // 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 ) { - if ( code === 'badtoken' ) { - cachedToken = null; // force a new token - api.postWithEditToken( params, ok, err ); - } else { - err( code, result ); - } - }; - return api.post( params, { ok : ok, err : getTokenIfBad }); - } - }, - - /** - * Api helper to grab an edit token - * - * token callback has signature ( String token ) - * error callback has signature ( String code, Object results, XmlHttpRequest xhr, Exception exception ) - * Note that xhr and exception are only available for 'http_*' errors - * code may be any http_* error code (see mw.Api), or 'token_missing' - * - * @param tokenCallback {Function} received token callback - * @param err {Function} error callback - * @return {jqXHR} - */ - 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' - }, - ok = function( data ) { - var token; - $.each( data.query.pages, function( i, page ) { - if ( page.edittoken ) { - token = page.edittoken; - return false; - } - } ); - if ( token !== undefined ) { - cachedToken = token; - tokenCallback( token ); - } else { - err( 'token-missing', data ); - } - }, - ajaxOptions = { - ok: ok, - err: err, - // Due to the API assuming we're logged out if we pass the callback-parameter, - // we have to disable jQuery's callback system, and instead parse JSON string, - // by setting 'jsonp' to false. - jsonp: false - }; - - return this.get( parameters, ajaxOptions ); - }, - - /** - * Create a new section of the page. - * @param title {mw.Title|String} target page - * @param header {String} - * @param message {String} wikitext message - * @param ok {Function} success handler - * @param err {Function} error handler - * @return {jqXHR} - */ - newSection: function( title, header, message, ok, err ) { - var params = { - action: 'edit', - section: 'new', - format: 'json', - title: title.toString(), - summary: header, - text: message - }; - return this.postWithEditToken( params, ok, err ); - } - - } ); - -} )( jQuery, mediaWiki ); diff --git a/resources/mediawiki/mediawiki.api.js b/resources/mediawiki/mediawiki.api.js deleted file mode 100644 index 225093b36b..0000000000 --- a/resources/mediawiki/mediawiki.api.js +++ /dev/null @@ -1,224 +0,0 @@ -/* mw.Api objects represent the API of a particular MediaWiki server. */ - -( function( $, mw, undefined ) { - - /** - * @var defaultOptions {Object} - * We allow people to omit these default parameters from API requests - * there is very customizable error handling here, on a per-call basis - * wondering, would it be simpler to make it easy to clone the api object, - * change error handling, and use that instead? - */ - var defaultOptions = { - - // Query parameters for API requests - parameters: { - action: 'query', - format: 'json' - }, - - // Ajax options for jQuery.ajax() - 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 - - dataType: 'json' - } - }; - - /** - * Constructor to create an object to interact with the API of a particular MediaWiki server. - * - * @todo Share API objects with exact same config. - * @example - * - * var api = new mw.Api(); - * api.get( { - * action: 'query', - * meta: 'userinfo' - * }, { - * ok: function () { console.log( arguments ); } - * } ); - * - * - * @constructor - * @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 ) { - - if ( options === undefined ) { - options = {}; - } - - // Force toString if we got a mw.Uri object - if ( options.ajax && options.ajax.url !== undefined ) { - options.ajax.url = String( options.ajax.url ); - } - - options.parameters = $.extend( {}, defaultOptions.parameters, options.parameters ); - options.ajax = $.extend( {}, defaultOptions.ajax, options.ajax ); - - this.defaults = options; - }; - - 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. - * - * @param {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; - if ( typeof arg === 'function' ) { - opt = { 'ok': arg }; - } - if ( !opt.ok ) { - throw new Error( 'ajax options must include ok callback' ); - } - return opt; - }, - - /** - * Perform API get request - * - * @param {Object} request parameters - * @param {Object|Function} ajax options, or just a success function - * @return {jqXHR} - */ - get: function( parameters, ajaxOptions ) { - ajaxOptions = this.normalizeAjaxOptions( ajaxOptions ); - ajaxOptions.type = 'GET'; - return this.ajax( parameters, ajaxOptions ); - }, - - /** - * Perform API post request - * @todo Post actions for nonlocal will need proxy - * - * @param {Object} request parameters - * @param {Object|Function} ajax options, or just a success function - * @return {jqXHR} - */ - post: function( parameters, ajaxOptions ) { - ajaxOptions = this.normalizeAjaxOptions( ajaxOptions ); - ajaxOptions.type = 'POST'; - return this.ajax( parameters, ajaxOptions ); - }, - - /** - * Perform the API call. - * - * @param {Object} request parameters - * @param {Object} ajax options - * @return {jqXHR} - */ - ajax: function( parameters, ajaxOptions ) { - parameters = $.extend( {}, this.defaults.parameters, parameters ); - ajaxOptions = $.extend( {}, this.defaults.ajax, ajaxOptions ); - - // 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 - } ); - }; - - // 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 ); - } - - }; - - /** - * @var {Array} List of errors we might receive from the API. - * For now, this just documents our expectation that there should be similar messages - * available. - */ - mw.Api.errors = [ - // occurs when POST aborted - // jQuery 1.4 can't distinguish abort or lost connection from 200 OK + empty result - 'ok-but-empty', - - // timeout - 'timeout', - - // really a warning, but we treat it like an error - 'duplicate', - 'duplicate-archive', - - // upload succeeded, but no image info. - // this is probably impossible, but might as well check for it - 'noimageinfo', - // remote errors, defined in API - 'uploaddisabled', - 'nomodule', - 'mustbeposted', - 'badaccess-groups', - 'stashfailed', - 'missingresult', - 'missingparam', - 'invalid-file-key', - 'copyuploaddisabled', - 'mustbeloggedin', - 'empty-file', - 'file-too-large', - 'filetype-missing', - 'filetype-banned', - 'filename-tooshort', - 'illegal-filename', - 'verification-error', - 'hookaborted', - 'unknown-error', - 'internal-error', - 'overwrite', - 'badtoken', - 'fetchfileerror', - 'fileexists-shared-forbidden', - 'invalidtitle', - 'notloggedin' - ]; - - /** - * @var {Array} List of warnings we might receive from the API. - * For now, this just documents our expectation that there should be similar messages - * available. - */ - mw.Api.warnings = [ - 'duplicate', - 'exists' - ]; - -})( jQuery, mediaWiki ); diff --git a/resources/mediawiki/mediawiki.api.parse.js b/resources/mediawiki/mediawiki.api.parse.js deleted file mode 100644 index 1cc68f29cf..0000000000 --- a/resources/mediawiki/mediawiki.api.parse.js +++ /dev/null @@ -1,31 +0,0 @@ -/** - * Additional mw.Api methods to assist with API calls related to parsing wikitext. - */ - -( 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} - */ - parse: function( wikiText, success, err ) { - var params = { - text: wikiText, - action: 'parse' - }, - ok = function( data ) { - if ( data.parse && data.parse.text && data.parse.text['*'] ) { - success( data.parse.text['*'] ); - } - }; - return this.get( params, { ok: ok, err: err } ); - } - - } ); - -} )( jQuery, mediaWiki ); diff --git a/resources/mediawiki/mediawiki.api.titleblacklist.js b/resources/mediawiki/mediawiki.api.titleblacklist.js deleted file mode 100644 index 5435945b60..0000000000 --- a/resources/mediawiki/mediawiki.api.titleblacklist.js +++ /dev/null @@ -1,51 +0,0 @@ -/** - * Additional mw.Api methods to assist with API calls to the API module of the TitleBlacklist extension. - */ - -( function( $, mw, undefined ) { - - $.extend( mw.Api.prototype, { - /** - * Convinience method for 'action=titleblacklist'. - * Note: This action is not provided by MediaWiki core, but as part of the TitleBlacklist extension. - * - * @param title {mw.Title} - * @param success {Function} Called on successfull request. First argument is false if title wasn't blacklisted, - * object with 'reason', 'line' and 'message' properties if title was blacklisted. - * @param err {Function} optional callback to run if api error - * @return {jqXHR} - */ - isBlacklisted: function( title, success, err ) { - var params = { - action: 'titleblacklist', - tbaction: 'create', - tbtitle: title.toString() - }, - ok = function( data ) { - var result; - - // this fails open (if nothing valid is returned by the api, allows the title) - // also fails open when the API is not present, which will be most of the time - // as this API module is part of the TitleBlacklist extension. - if ( data.titleblacklist && data.titleblacklist.result && data.titleblacklist.result === 'blacklisted') { - if ( data.titleblacklist.reason ) { - result = { - reason: data.titleblacklist.reason, - line: data.titleblacklist.line, - message: data.titleblacklist.message - }; - } else { - mw.log('mw.Api.titleblacklist::isBlacklisted> no reason data for blacklisted title', 'debug'); - result = { reason: 'Blacklisted, but no reason supplied', line: 'Unknown', message: null }; - } - success( result ); - } else { - success ( false ); - } - }; - - return this.get( params, { ok: ok, err: err } ); - } - - } ); -} )( jQuery, mediaWiki ); diff --git a/resources/mediawiki/mediawiki.api.watch.js b/resources/mediawiki/mediawiki.api.watch.js deleted file mode 100644 index 3f2525ad30..0000000000 --- a/resources/mediawiki/mediawiki.api.watch.js +++ /dev/null @@ -1,58 +0,0 @@ -/** - * Additional mw.Api methods to assist with (un)watching wiki pages. - * @since 1.19 - */ -( function( $, mw ) { - - $.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 - * 'message' (parsed HTML of the 'addedwatchtext' message). - * @param err {Function} callback if error (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 } ); - }, - /** - * Convinience method for 'action=watch&unwatch='. - * - * @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 - * 'message' (parsed HTML of the 'removedwatchtext' message). - * @param err {Function} callback if error (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 } ); - } - - } ); - -} )( jQuery, mediaWiki );