Merge "Update grunt-jscs to 2.5.0"
[lhc/web/wiklou.git] / resources / src / mediawiki.messagePoster / mediawiki.messagePoster.factory.js
1 /*global OO*/
2 ( function ( mw, $ ) {
3 /**
4 * This is a factory for MessagePoster objects, which allows a pluggable to way to script leaving a
5 * talk page message.
6 *
7 * @class mw.messagePoster.factory
8 * @singleton
9 */
10 function MwMessagePosterFactory() {
11 this.contentModelToClass = {};
12 }
13
14 OO.initClass( MwMessagePosterFactory );
15
16 // Note: This registration scheme is currently not compatible with LQT, since that doesn't
17 // have its own content model, just islqttalkpage. LQT pages will be passed to the wikitext
18 // MessagePoster.
19 /**
20 * Registers a MessagePoster subclass for a given content model.
21 *
22 * @param {string} contentModel Content model of pages this MessagePoster can post to
23 * @param {Function} messagePosterConstructor Constructor for MessagePoster
24 */
25 MwMessagePosterFactory.prototype.register = function ( contentModel, messagePosterConstructor ) {
26 if ( this.contentModelToClass[ contentModel ] !== undefined ) {
27 throw new Error( 'The content model \'' + contentModel + '\' is already registered.' );
28 }
29
30 this.contentModelToClass[ contentModel ] = messagePosterConstructor;
31 };
32
33 /**
34 * Unregisters a given content model
35 * This is exposed for testing and should not normally be needed.
36 *
37 * @param {string} contentModel Content model to unregister
38 */
39 MwMessagePosterFactory.prototype.unregister = function ( contentModel ) {
40 delete this.contentModelToClass[ contentModel ];
41 };
42
43 /**
44 * Creates a MessagePoster, given a title. A promise for this is returned.
45 * This works by determining the content model, then loading the corresponding
46 * module (which will register the MessagePoster class), and finally constructing it.
47 *
48 * This does not require the message and should be called as soon as possible, so it does the
49 * API and ResourceLoader requests in the background.
50 *
51 * @param {mw.Title} title Title that will be posted to
52 * @param {string} [apiUrl] api.php URL if the title is on another wiki
53 * @return {jQuery.Promise} Promise resolving to a mw.messagePoster.MessagePoster.
54 * For failure, rejected with up to three arguments:
55 *
56 * - errorCode Error code string
57 * - error Error explanation
58 * - details Further error details
59 */
60 MwMessagePosterFactory.prototype.create = function ( title, apiUrl ) {
61 var pageId, page, contentModel, moduleName, api,
62 factory = this;
63
64 if ( apiUrl ) {
65 api = new mw.ForeignApi( apiUrl );
66 } else {
67 api = mw.Api();
68 }
69
70 return api.get( {
71 action: 'query',
72 prop: 'info',
73 indexpageids: true,
74 titles: title.getPrefixedDb()
75 } ).then( function ( result ) {
76 if ( result.query.pageids && result.query.pageids.length > 0 ) {
77 pageId = result.query.pageids[ 0 ];
78 page = result.query.pages[ pageId ];
79
80 contentModel = page.contentmodel;
81 moduleName = 'mediawiki.messagePoster.' + contentModel;
82 return mw.loader.using( moduleName ).then( function () {
83 return factory.createForContentModel(
84 contentModel,
85 title,
86 api
87 );
88 }, function () {
89 return $.Deferred().reject( 'failed-to-load-module', 'Failed to load the \'' + moduleName + '\' module' );
90 } );
91 } else {
92 return $.Deferred().reject( 'unexpected-response', 'Unexpected API response' );
93 }
94 }, function ( errorCode, details ) {
95 return $.Deferred().reject( 'content-model-query-failed', errorCode, details );
96 } ).promise();
97 };
98
99 /**
100 * Creates a MessagePoster instance, given a title and content model
101 *
102 * @private
103 *
104 * @param {string} contentModel Content model of title
105 * @param {mw.Title} title Title being posted to
106 * @param {mw.Api} api mw.Api instance that the instance should use
107 * @return {mw.messagePoster.MessagePoster}
108 *
109 */
110 MwMessagePosterFactory.prototype.createForContentModel = function ( contentModel, title, api ) {
111 return new this.contentModelToClass[ contentModel ]( title, api );
112 };
113
114 mw.messagePoster = {
115 factory: new MwMessagePosterFactory()
116 };
117 }( mediaWiki, jQuery ) );