| Current File : /home/jvzmxxx/wiki1/extensions/MobileFrontend/resources/mobile.editor.api/EditorGateway.js |
( function ( M, $ ) {
/**
* API that helps save and retrieve page content
* @class EditorGateway
*
* @constructor
* @param {Object} options Configuration options
* @param {mw.Api} options.api an Api to use.
* @param {string} options.title the title to edit
* @param {number} options.sectionId the id of the section to operate edits on.
* @param {number} [options.oldId] revision to operate on. If absent defaults to latest.
* @param {boolean} [options.isNewPage] whether the page being created is new
*/
function EditorGateway( options ) {
this.api = options.api;
this.title = options.title;
this.sectionId = options.sectionId;
this.oldId = options.oldId;
// return an empty section for new pages
this.content = options.isNewPage ? '' : undefined;
this.hasChanged = false;
}
EditorGateway.prototype = {
/**
* Get the content of a page.
* @method
* @return {jQuery.Deferred}
*/
getContent: function () {
var options,
self = this,
result = $.Deferred();
if ( this.content !== undefined ) {
result.resolve( this.content );
} else {
options = {
action: 'query',
prop: 'revisions',
rvprop: [ 'content', 'timestamp' ],
titles: this.title,
// get block information for this user
meta: 'userinfo',
uiprop: 'blockinfo',
formatversion: 2
};
// Load text of old revision if desired
if ( this.oldId ) {
options.rvstartid = this.oldId;
}
// See Bug 50136 - passing rvsection will fail with non wikitext
if ( $.isNumeric( this.sectionId ) ) {
options.rvsection = this.sectionId;
}
this.api.get( options ).done( function ( resp ) {
var revision, pageObj;
if ( resp.error ) {
result.reject( resp.error.code );
return;
}
pageObj = resp.query.pages[0];
// page might not exist and caller might not have known.
if ( pageObj.hasOwnProperty( 'missing' ) ) {
self.content = '';
} else {
revision = pageObj.revisions[0];
self.content = revision.content;
self.timestamp = revision.timestamp;
}
// save content a second time to be able to check for changes
self.originalContent = self.content;
result.resolve( self.content, resp.query.userinfo );
} );
}
return result;
},
/**
* Mark content as modified and set changes to be submitted when #save
* is invoked.
* @method
* @param {string} content New section content.
*/
setContent: function ( content ) {
if ( this.originalContent !== content ) {
this.hasChanged = true;
} else {
this.hasChanged = false;
}
this.content = content;
},
/**
* Mark content as modified and set text that should be prepended to given
* section when #save is invoked.
* @method
* @param {string} text Text to be prepended.
*/
setPrependText: function ( text ) {
this.prependtext = text;
this.hasChanged = true;
},
/**
* Save the new content of the section, previously set using #setContent.
* @method
* @param {Object} options Configuration options
* @param {string} [options.summary] Optional summary for the edit.
* @param {string} [options.captchaId] If CAPTCHA was requested, ID of the
* captcha.
* @param {string} [options.captchaWord] If CAPTCHA was requested, term
* displayed in the CAPTCHA.
* @return {jQuery.Deferred} On failure callback is passed an object with
* `type` and `details` properties. `type` is a string describing the type
* of error, `details` can be any object (usually error message).
*/
save: function ( options ) {
var self = this,
result = $.Deferred();
options = options || {};
/**
* Save content. Make an API request.
* @ignore
*/
function saveContent() {
var apiOptions = {
action: 'edit',
title: self.title,
summary: options.summary,
captchaid: options.captchaId,
captchaword: options.captchaWord,
basetimestamp: self.timestamp,
starttimestamp: self.timestamp
};
if ( self.content !== undefined ) {
apiOptions.text = self.content;
} else if ( self.prependtext ) {
apiOptions.prependtext = self.prependtext;
}
if ( $.isNumeric( self.sectionId ) ) {
apiOptions.section = self.sectionId;
}
self.api.postWithToken( 'edit', apiOptions ).done( function ( data ) {
var code, warning;
if ( data && data.edit && data.edit.result === 'Success' ) {
self.hasChanged = false;
result.resolve();
} else if ( data && data.error ) {
// Edit API error
result.reject( {
type: 'error',
details: data.error.code
} );
} else if ( data && data.edit && data.edit.captcha ) {
// CAPTCHAs
result.reject( {
type: 'captcha',
details: data.edit.captcha
} );
} else if ( data && data.edit && data.edit.code ) {
code = data.edit.code;
warning = data.edit.warning;
// FIXME: AbuseFilter should have more consistent API responses
if ( /^abusefilter-warning/.test( code ) ) {
// AbuseFilter warning
result.reject( {
type: 'abusefilter',
details: {
type: 'warning',
message: warning
}
} );
} else if ( /^abusefilter-disallow/.test( code ) ) {
// AbuseFilter disallow
result.reject( {
type: 'abusefilter',
details: {
type: 'disallow',
message: warning
}
} );
} else if ( /^abusefilter/.test( code ) ) {
// AbuseFilter other
result.reject( {
type: 'abusefilter',
details: {
type: 'other',
message: warning
}
} );
} else {
// other errors
result.reject( {
type: 'error',
details: code
} );
}
} else {
result.reject( {
type: 'error',
details: 'unknown'
} );
}
} ).fail( $.proxy( result, 'reject', {
type: 'error',
details: 'http'
} ) );
}
saveContent();
return result;
},
/**
* Abort any pending previews.
* @method
*/
abortPreview: function () {
if ( this._pending ) {
this._pending.abort();
}
},
/**
* Get page preview from the API and abort any existing previews.
* @method
* @param {Object} options API query parameters
* @return {jQuery.Deferred}
*/
getPreview: function ( options ) {
var result = $.Deferred(),
sectionLine = '',
self = this;
$.extend( options, {
action: 'parse',
// Enable section preview mode to avoid errors (bug 49218)
sectionpreview: true,
// needed for pre-save transform to work (bug 53692)
pst: true,
// Output mobile HTML (bug 54243)
mobileformat: true,
title: this.title,
prop: [ 'text', 'sections' ]
} );
this.abortPreview();
this._pending = this.api.post( options ).done( function ( resp ) {
if ( resp && resp.parse && resp.parse.text ) {
// section 0 haven't a section name so skip
if ( self.sectionId !== 0 &&
resp.parse.sections !== undefined &&
resp.parse.sections[0] !== undefined &&
resp.parse.sections[0].line !== undefined
) {
sectionLine = resp.parse.sections[0].line;
}
result.resolve( resp.parse.text['*'], sectionLine );
} else {
result.reject();
}
} ).fail( $.proxy( result, 'reject' ) );
return result;
}
};
M.define( 'mobile.editor.api/EditorGateway', EditorGateway );
}( mw.mobileFrontend, jQuery ) );