mw.Upload.BookletLayout: Fail when unable to load config from foreign wiki
[lhc/web/wiklou.git] / resources / src / mediawiki / mediawiki.ForeignStructuredUpload.js
1 ( function ( mw, $, OO ) {
2 /**
3 * @class mw.ForeignStructuredUpload
4 * @extends mw.ForeignUpload
5 *
6 * Used to represent an upload in progress on the frontend.
7 *
8 * This subclass will upload to a wiki using a structured metadata
9 * system similar to (or identical to) the one on Wikimedia Commons.
10 *
11 * See <https://commons.wikimedia.org/wiki/Commons:Structured_data> for
12 * a more detailed description of how that system works.
13 *
14 * **TODO: This currently only supports uploads under CC-BY-SA 4.0,
15 * and should really have support for more licenses.**
16 *
17 * @inheritdoc
18 */
19 function ForeignStructuredUpload( target, apiconfig ) {
20 this.date = undefined;
21 this.descriptions = [];
22 this.categories = [];
23
24 // Config for uploads to local wiki.
25 // Can be overridden with foreign wiki config when #loadConfig is called.
26 this.config = mw.config.get( 'wgUploadDialog' );
27
28 mw.ForeignUpload.call( this, target, apiconfig );
29 }
30
31 OO.inheritClass( ForeignStructuredUpload, mw.ForeignUpload );
32
33 /**
34 * Get the configuration for the form and filepage from the foreign wiki, if any, and use it for
35 * this upload.
36 *
37 * @return {jQuery.Promise} Promise returning config object
38 */
39 ForeignStructuredUpload.prototype.loadConfig = function () {
40 var deferred,
41 upload = this;
42
43 if ( this.configPromise ) {
44 return this.configPromise;
45 }
46
47 if ( this.target === 'local' ) {
48 deferred = $.Deferred();
49 setTimeout( function () {
50 // Resolve asynchronously, so that it's harder to accidentally write synchronous code that
51 // will break for cross-wiki uploads
52 deferred.resolve( upload.config );
53 } );
54 this.configPromise = deferred.promise();
55 } else {
56 this.configPromise = this.apiPromise.then( function ( api ) {
57 // Get the config from the foreign wiki
58 return api.get( {
59 action: 'query',
60 meta: 'siteinfo',
61 siprop: 'uploaddialog',
62 // For convenient true/false booleans
63 formatversion: 2
64 } ).then( function ( resp ) {
65 // Foreign wiki might be running a pre-1.27 MediaWiki, without support for this
66 if ( resp.query && resp.query.uploaddialog ) {
67 upload.config = resp.query.uploaddialog;
68 return upload.config;
69 } else {
70 return $.Deferred().reject( 'upload-foreign-cant-load-config' );
71 }
72 }, function () {
73 return $.Deferred().reject( 'upload-foreign-cant-load-config' );
74 } );
75 } );
76 }
77
78 return this.configPromise;
79 };
80
81 /**
82 * Add categories to the upload.
83 *
84 * @param {string[]} categories Array of categories to which this upload will be added.
85 */
86 ForeignStructuredUpload.prototype.addCategories = function ( categories ) {
87 var i, category;
88
89 for ( i = 0; i < categories.length; i++ ) {
90 category = categories[ i ];
91 this.categories.push( category );
92 }
93 };
94
95 /**
96 * Empty the list of categories for the upload.
97 */
98 ForeignStructuredUpload.prototype.clearCategories = function () {
99 this.categories = [];
100 };
101
102 /**
103 * Add a description to the upload.
104 *
105 * @param {string} language The language code for the description's language. Must have a template on the target wiki to work properly.
106 * @param {string} description The description of the file.
107 */
108 ForeignStructuredUpload.prototype.addDescription = function ( language, description ) {
109 this.descriptions.push( {
110 language: language,
111 text: description
112 } );
113 };
114
115 /**
116 * Empty the list of descriptions for the upload.
117 */
118 ForeignStructuredUpload.prototype.clearDescriptions = function () {
119 this.descriptions = [];
120 };
121
122 /**
123 * Set the date of creation for the upload.
124 *
125 * @param {Date} date
126 */
127 ForeignStructuredUpload.prototype.setDate = function ( date ) {
128 this.date = date;
129 };
130
131 /**
132 * Get the text of the file page, to be created on upload. Brings together
133 * several different pieces of information to create useful text.
134 *
135 * @return {string}
136 */
137 ForeignStructuredUpload.prototype.getText = function () {
138 return this.config.format.filepage
139 // Replace "numbered parameters" with the given information
140 .replace( '$DESCRIPTION', this.getDescriptions() )
141 .replace( '$DATE', this.getDate() )
142 .replace( '$SOURCE', this.getSource() )
143 .replace( '$AUTHOR', this.getUser() )
144 .replace( '$LICENSE', this.getLicense() )
145 .replace( '$CATEGORIES', this.getCategories() );
146 };
147
148 /**
149 * @inheritdoc
150 */
151 ForeignStructuredUpload.prototype.getComment = function () {
152 return this.config.comment
153 .replace( '$PAGENAME', mw.config.get( 'wgPageName' ) )
154 .replace( '$HOST', location.host );
155 };
156
157 /**
158 * Gets the wikitext for the creation date of this upload.
159 *
160 * @private
161 * @return {string}
162 */
163 ForeignStructuredUpload.prototype.getDate = function () {
164 if ( !this.date ) {
165 return '';
166 }
167
168 return this.date.toString();
169 };
170
171 /**
172 * Fetches the wikitext for any descriptions that have been added
173 * to the upload.
174 *
175 * @private
176 * @return {string}
177 */
178 ForeignStructuredUpload.prototype.getDescriptions = function () {
179 var i, desc, templateCalls = [];
180
181 for ( i = 0; i < this.descriptions.length; i++ ) {
182 desc = this.descriptions[ i ];
183 templateCalls.push(
184 this.config.format.description
185 .replace( '$LANGUAGE', desc.language )
186 .replace( '$TEXT', desc.text )
187 );
188 }
189
190 return templateCalls.join( '\n' );
191 };
192
193 /**
194 * Fetches the wikitext for the categories to which the upload will
195 * be added.
196 *
197 * @private
198 * @return {string}
199 */
200 ForeignStructuredUpload.prototype.getCategories = function () {
201 var i, cat, categoryLinks = [];
202
203 if ( this.categories.length === 0 ) {
204 return this.config.format.uncategorized;
205 }
206
207 for ( i = 0; i < this.categories.length; i++ ) {
208 cat = this.categories[ i ];
209 categoryLinks.push( '[[Category:' + cat + ']]' );
210 }
211
212 return categoryLinks.join( '\n' );
213 };
214
215 /**
216 * Gets the wikitext for the license of the upload.
217 *
218 * @private
219 * @return {string}
220 */
221 ForeignStructuredUpload.prototype.getLicense = function () {
222 return this.config.format.license;
223 };
224
225 /**
226 * Get the source. This should be some sort of localised text for "Own work".
227 *
228 * @private
229 * @return {string}
230 */
231 ForeignStructuredUpload.prototype.getSource = function () {
232 return this.config.format.ownwork;
233 };
234
235 /**
236 * Get the username.
237 *
238 * @private
239 * @return {string}
240 */
241 ForeignStructuredUpload.prototype.getUser = function () {
242 var username, namespace;
243 // Do not localise, we don't know the language of target wiki
244 namespace = 'User';
245 username = mw.config.get( 'wgUserName' );
246 if ( !username ) {
247 // The user is not logged in locally. However, they might be logged in on the foreign wiki.
248 // We should record their username there. (If they're not logged in there either, this will
249 // record the IP address.) It's also possible that the user opened this dialog, got an error
250 // about not being logged in, logged in in another browser tab, then continued uploading.
251 username = '{{subst:REVISIONUSER}}';
252 }
253 return '[[' + namespace + ':' + username + '|' + username + ']]';
254 };
255
256 mw.ForeignStructuredUpload = ForeignStructuredUpload;
257 }( mediaWiki, jQuery, OO ) );