diff options
author | Pierre Schmitz <pierre@archlinux.de> | 2012-05-03 13:01:35 +0200 |
---|---|---|
committer | Pierre Schmitz <pierre@archlinux.de> | 2012-05-03 13:01:35 +0200 |
commit | d9022f63880ce039446fba8364f68e656b7bf4cb (patch) | |
tree | 16b40fbf17bf7c9ee6f4ead25b16dd192378050a /resources/mediawiki.api | |
parent | 27cf83d177256813e2e802241085fce5dd0f3fb9 (diff) |
Update to MediaWiki 1.19.0
Diffstat (limited to 'resources/mediawiki.api')
-rw-r--r-- | resources/mediawiki.api/mediawiki.api.category.js | 105 | ||||
-rw-r--r-- | resources/mediawiki.api/mediawiki.api.edit.js | 119 | ||||
-rw-r--r-- | resources/mediawiki.api/mediawiki.api.js | 224 | ||||
-rw-r--r-- | resources/mediawiki.api/mediawiki.api.parse.js | 31 | ||||
-rw-r--r-- | resources/mediawiki.api/mediawiki.api.titleblacklist.js | 51 | ||||
-rw-r--r-- | resources/mediawiki.api/mediawiki.api.watch.js | 58 |
6 files changed, 588 insertions, 0 deletions
diff --git a/resources/mediawiki.api/mediawiki.api.category.js b/resources/mediawiki.api/mediawiki.api.category.js new file mode 100644 index 00000000..c8c18e69 --- /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 00000000..a9d488a8 --- /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 00000000..225093b3 --- /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 + * <code> + * var api = new mw.Api(); + * api.get( { + * action: 'query', + * meta: 'userinfo' + * }, { + * ok: function () { console.log( arguments ); } + * } ); + * </code> + * + * @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 00000000..1cc68f29 --- /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 00000000..5435945b --- /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 00000000..3f2525ad --- /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 ); |