| Current File : /home/jvzmxxx/wiki/extensions/Flow/modules/flow/dm/api/mw.flow.dm.APIHandler.js |
( function ( $ ) {
/**
* Resource Provider object.
*
* @class
*
* @constructor
* @param {string} page Full page name with its namespace;
* for example: "User_talk:Foo"
* @param {Object} [config] Configuration options
* @cfg {Object} [currentRevision] Current revision Id. Mostly used
* for edit conflict check.
* @cfg {Object} [apiConstructorParams] Parameters for mw.Api()
* @cfg {Object} [requestParams] Parameters for the request
*/
mw.flow.dm.APIHandler = function FlowDmAPIHandler( page, config ) {
config = config || {};
this.apiConstructorParams = $.extend( {
ajax: {
timeout: 5 * 1000, // 5 seconds
cache: false
}
}, config.apiConstructorParams );
this.page = page;
this.setCurrentRevision( config.currentRevision );
this.requestParams = $.extend( {
action: 'flow',
uselang: mw.config.get( 'wgUserLanguage' )
}, config.requestParams );
};
OO.initClass( mw.flow.dm.APIHandler );
/**
* Set the current revision Id. This is mostly used for edit actions, to check
* for edit conflicts.
*
* @param {string} revisionId Current revision id
*/
mw.flow.dm.APIHandler.prototype.setCurrentRevision = function ( revisionId ) {
this.currentRevision = revisionId;
};
/**
* General get request
* @param {string} submodule The requested submodule
* @param {Object} requestParams API request parameters
* @return {jQuery.Promise} Promise that is resolved when the API request
* is done, with the API result.
*/
mw.flow.dm.APIHandler.prototype.get = function ( submodule, requestParams ) {
var xhr,
params = $.extend( { submodule: submodule }, this.requestParams, requestParams );
xhr = ( new mw.Api() ).get( params );
return xhr
.then( function ( data ) {
return data.flow[ submodule ].result;
} )
.promise( { abort: xhr.abort } );
};
/**
* Post with edit token request
*
* @param {string} submodule The requested submodule
* @param {Object} requestParams API request parameters
* @return {jQuery.Promise} Promise that is resolved when the API request
* is done, with the API result.
*/
mw.flow.dm.APIHandler.prototype.postEdit = function ( submodule, requestParams ) {
var params = $.extend( { submodule: submodule }, this.requestParams, requestParams );
return ( new mw.Api() ).postWithToken( 'csrf', params );
};
/**
* Get page categories. This will recursively continue to fetch results
* until all page categories are fetched.
*
* @return {jQuery.Promise} Promise that is resolved when the API request
* is done, with the API result.
*/
mw.flow.dm.APIHandler.prototype.getCategories = function () {
var params = {
action: 'query',
titles: this.page,
generator: 'categories',
gcllimit: 'max'
};
return ( new mw.Api() ).get( $.extend( {}, this.requestParams, params ) )
.then( function ( response ) {
return OO.getProp( response, 'query', 'pages' );
} );
};
/**
* Gets the reason the page was protected
*
* @return {jQuery.Promise}
* @return {Function} return.done
* @return {string} return.done.reason Reason, as HTML
*/
mw.flow.dm.APIHandler.prototype.getProtectionReason = function () {
var params = {
action: 'query',
list: 'logevents',
leprop: 'parsedcomment',
leaction: 'protect/protect',
letitle: this.page,
lelimit: 1
};
return ( new mw.Api() ).get( $.extend( {}, this.requestParams, params ) )
.then( function ( response ) {
return OO.getProp( response, 'query', 'logevents', 0, 'parsedcomment' );
} );
};
/**
* Send a request to get topic list
*
* @param {string} orderType Sort order type, 'newest' or 'updated'
* @cfg {string} [offset] Topic offset id or timestamp offset
* if given, the topic list will be returned with topics that
* are after (and including) the topic with the given uuid or
* after the given timestamp.
* @cfg {string} [toconly] Receive a stripped reply that fits the ToC. For more information
* see 'toconly' in the API documentation.
* @return {jQuery.Promise} Promise that is resolved with the topiclist response
*/
mw.flow.dm.APIHandler.prototype.getTopicList = function ( orderType, config ) {
var params = {
page: this.page
};
config = config || {};
params.vtltoconly = !!config.toconly;
params.vtllimit = config.toconly ? 50 : 10;
params.vtlsortby = orderType;
if ( orderType === 'newest' ) {
params[ 'vtloffset-id' ] = config.offset;
} else if ( orderType === 'updated' ) {
// Translate api/object-given offset to MW offset for the API request
params.vtloffset = moment.utc( config.offset ).format( 'YYYYMMDDHHmmss' );
}
return this.get( 'view-topiclist', params )
.then( function ( data ) {
return data.topiclist;
} );
};
/**
* Adds CAPTCHA to parameters if applicable
*
* @param {Object} params API Parameters to add CAPTCHA information to
* @param {Object|null} captcha CAPTCHA object
* @param {string} captcha.id CAPTCHA ID
* @param {string} captcha.answer CAPTCHA answer (user-provided)
*/
mw.flow.dm.APIHandler.prototype.addCaptcha = function ( params, captcha ) {
// TODO: Find a better way to plug this in.
if ( captcha ) {
params.wpCaptchaId = captcha.id;
params.wpCaptchaWord = captcha.answer;
}
};
/**
* Get topic title from topic id
*
* @param {string} topicId Topic id
* @return {string} Topic title
*/
mw.flow.dm.APIHandler.prototype.getTopicTitle = function ( topicId ) {
return ( new mw.Title( topicId, 2600 ) ).getPrefixedDb();
};
/**
* Send an edit request to the API to save a reply.
*
* @param {string} topicId Topic Id
* @param {string} replyTo The parent of this reply
* @param {string} content Reply content
* @param {string} format Reply content format
* @param {Object} [captcha] CAPTCHA information
* @return {jQuery.Promise} Promise that is resolved with the id of the workflow
* that this reply belongs to
*/
mw.flow.dm.APIHandler.prototype.saveReply = function ( topicId, replyTo, content, format, captcha ) {
var params = {
action: 'flow',
submodule: 'reply',
page: 'Topic:' + topicId,
repreplyTo: replyTo,
repcontent: content,
repformat: format
};
this.addCaptcha( params, captcha );
return ( new mw.Api() ).postWithToken( 'csrf', $.extend( {}, this.requestParams, params ) )
.then( function ( data ) {
return data.flow.reply.workflow;
} );
};
/**
* Save new topic in the board
*
* @param {string} title Topic title
* @param {string} content Topic content
* @param {string} format Content format
* @param {Object} [captcha] CAPTCHA information
* @return {jQuery.Promise} Promise that is resolved with the new topic id
*/
mw.flow.dm.APIHandler.prototype.saveNewTopic = function ( title, content, format, captcha ) {
var params = {
submodule: 'new-topic',
page: this.page,
nttopic: title,
ntcontent: content,
ntformat: format
};
this.addCaptcha( params, captcha );
return ( new mw.Api() ).postWithToken( 'csrf', $.extend( {}, this.requestParams, params ) )
.then( function ( response ) {
return OO.getProp( response.flow, 'new-topic', 'committed', 'topiclist', 'topic-id' );
} );
};
/**
* Get the board description from the API.
*
* @param {string} [contentFormat='fixed-html'] Content format for board description
* @return {jQuery.Promise} Promise that is resolved with the header revision data
*/
mw.flow.dm.APIHandler.prototype.getDescription = function ( contentFormat ) {
var params = {
page: this.page,
vhformat: contentFormat || 'fixed-html'
};
return this.get( 'view-header', params )
.then( function ( data ) {
return data.header.revision;
} );
};
/**
* Save header information.
*
* @param {string} content Header content
* @param {string} format Content format for board description
* @param {Object} [captcha] CAPTCHA information
* @return {jQuery.Promise} Promise that is resolved with the saved header revision id
*/
mw.flow.dm.APIHandler.prototype.saveDescription = function ( content, format, captcha ) {
var xhr,
params = {
page: this.page,
ehcontent: content,
ehformat: format,
ehprev_revision: this.currentRevision
};
this.addCaptcha( params, captcha );
xhr = this.postEdit( 'edit-header', params )
.then( function ( data ) {
return OO.getProp( data.flow, 'edit-header', 'committed', 'header', 'header-revision-id' );
} );
return xhr.promise( { abort: xhr.abort } );
};
/**
* Get a post.
*
* @param {string} postId
* @param {string} format
* @return {jQuery.Promise} Promise that is resolved with the post revision data
*/
mw.flow.dm.APIHandler.prototype.getPost = function ( topicId, postId, format ) {
var params = {
page: this.getTopicTitle( topicId ),
vppostId: postId,
vpformat: format || 'html'
};
return this.get( 'view-post', params )
.then( function ( data ) {
return data.topic.revisions[ data.topic.posts[ postId ] ];
} );
};
/**
* Save a post.
*
* @param {string} topicId
* @param {string} postId
* @param {string} content
* @param {string} format
* @param {string} [captcha] CAPTCHA information
* @return {jQuery.Promise} Promise that is resolved with the saved post revision id
*/
mw.flow.dm.APIHandler.prototype.savePost = function ( topicId, postId, content, format, captcha ) {
var params = {
page: this.getTopicTitle( topicId ),
epcontent: content,
epformat: format,
epprev_revision: this.currentRevision,
eppostId: postId
};
this.addCaptcha( params, captcha );
return this.postEdit( 'edit-post', params )
.then( function ( data ) {
return OO.getProp( data.flow, 'edit-post', 'workflow' );
} );
};
/**
* Get a topic summary.
*
* @param {string} topicId
* @param {string} format
* @return {jQuery.Promise} Promise that is resolved with the topic summary revision
*/
mw.flow.dm.APIHandler.prototype.getTopicSummary = function ( topicId, format ) {
var params = {
page: this.getTopicTitle( topicId ),
vtsformat: format || 'html'
};
return this.get( 'view-topic-summary', params )
.then( function ( data ) {
return data.topicsummary.revision;
} );
};
/**
* Save a topic summary.
*
* @param {string} topicId
* @param {string} content
* @param {string} format
* @param {Object} captcha
* @return {jQuery.Promise} Promise that is resolved with workflow id
*/
mw.flow.dm.APIHandler.prototype.saveTopicSummary = function ( topicId, content, format, captcha ) {
var params = {
page: this.getTopicTitle( topicId ),
etssummary: content,
etsformat: format,
etsprev_revision: this.currentRevision
};
this.addCaptcha( params, captcha );
return this.postEdit( 'edit-topic-summary', params )
.then( function ( data ) {
return OO.getProp( data.flow, 'edit-topic-summary', 'workflow' );
} );
};
/**
* Save a topic title.
*
* @param {string} topicId
* @param {string} content
* @param {Object} captcha
* @return {jQuery.Promise} Promise that is resolved with workflow id
*/
mw.flow.dm.APIHandler.prototype.saveTopicTitle = function ( topicId, content, captcha ) {
var params = {
page: this.getTopicTitle( topicId ),
etcontent: content,
etprev_revision: this.currentRevision
};
this.addCaptcha( params, captcha );
return this.postEdit( 'edit-title', params )
.then( function ( data ) {
return OO.getProp( data.flow, 'edit-title', 'workflow' );
} );
};
/**
* Execute the 'lock-topic' moderation action against a topic. Can be used to resolve or reopen a topic.
*
* @param {string} topicId Id of the topic to moderate
* @param {string} moderationState Can be 'lock' or 'unlock'
* @param {string} reasonMsgKey Message key for the moderation reason
* @return {jQuery.Promise} Promise that is resolved with workflow id
*/
mw.flow.dm.APIHandler.prototype.lockTopic = function ( topicId, moderationState, reasonMsgKey ) {
var params = {
page: this.getTopicTitle( topicId ),
cotmoderationState: moderationState,
cotreason: mw.msg( reasonMsgKey )
};
return this.postEdit( 'lock-topic', params )
.then( function ( data ) {
return OO.getProp( data.flow, 'lock-topic', 'workflow' );
} );
};
/**
* Resolve a topic.
*
* @param {string} topicId
* @return {jQuery.Promise} Promise that is resolved with workflow id
*/
mw.flow.dm.APIHandler.prototype.resolveTopic = function ( topicId ) {
return this.lockTopic( topicId, 'lock', 'flow-rev-message-lock-topic-reason' );
};
/**
* Reopen a topic.
*
* @param {string} topicId
* @return {jQuery.Promise} Promise that is resolved with workflow id
*/
mw.flow.dm.APIHandler.prototype.reopenTopic = function ( topicId ) {
return this.lockTopic( topicId, 'unlock', 'flow-rev-message-restore-topic-reason' );
};
}( jQuery ) );