Merge "Highlight new requirement"
[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 }
69 return upload.config;
70 } );
71 } );
72 }
73
74 return this.configPromise;
75 };
76
77 /**
78 * Add categories to the upload.
79 *
80 * @param {string[]} categories Array of categories to which this upload will be added.
81 */
82 ForeignStructuredUpload.prototype.addCategories = function ( categories ) {
83 var i, category;
84
85 for ( i = 0; i < categories.length; i++ ) {
86 category = categories[ i ];
87 this.categories.push( category );
88 }
89 };
90
91 /**
92 * Empty the list of categories for the upload.
93 */
94 ForeignStructuredUpload.prototype.clearCategories = function () {
95 this.categories = [];
96 };
97
98 /**
99 * Add a description to the upload.
100 *
101 * @param {string} language The language code for the description's language. Must have a template on the target wiki to work properly.
102 * @param {string} description The description of the file.
103 */
104 ForeignStructuredUpload.prototype.addDescription = function ( language, description ) {
105 this.descriptions.push( {
106 language: language,
107 text: description
108 } );
109 };
110
111 /**
112 * Empty the list of descriptions for the upload.
113 */
114 ForeignStructuredUpload.prototype.clearDescriptions = function () {
115 this.descriptions = [];
116 };
117
118 /**
119 * Set the date of creation for the upload.
120 *
121 * @param {Date} date
122 */
123 ForeignStructuredUpload.prototype.setDate = function ( date ) {
124 this.date = date;
125 };
126
127 /**
128 * Get the text of the file page, to be created on upload. Brings together
129 * several different pieces of information to create useful text.
130 *
131 * @return {string}
132 */
133 ForeignStructuredUpload.prototype.getText = function () {
134 return this.config.format.filepage
135 // Replace "numbered parameters" with the given information
136 .replace( '$DESCRIPTION', this.getDescriptions() )
137 .replace( '$DATE', this.getDate() )
138 .replace( '$SOURCE', this.getSource() )
139 .replace( '$AUTHOR', this.getUser() )
140 .replace( '$LICENSE', this.getLicense() )
141 .replace( '$CATEGORIES', this.getCategories() );
142 };
143
144 /**
145 * @inheritdoc
146 */
147 ForeignStructuredUpload.prototype.getComment = function () {
148 return this.config.comment
149 .replace( '$PAGENAME', mw.config.get( 'wgPageName' ) )
150 .replace( '$HOST', location.host );
151 };
152
153 /**
154 * Gets the wikitext for the creation date of this upload.
155 *
156 * @private
157 * @return {string}
158 */
159 ForeignStructuredUpload.prototype.getDate = function () {
160 if ( !this.date ) {
161 return '';
162 }
163
164 return this.date.toString();
165 };
166
167 /**
168 * Fetches the wikitext for any descriptions that have been added
169 * to the upload.
170 *
171 * @private
172 * @return {string}
173 */
174 ForeignStructuredUpload.prototype.getDescriptions = function () {
175 var i, desc, templateCalls = [];
176
177 for ( i = 0; i < this.descriptions.length; i++ ) {
178 desc = this.descriptions[ i ];
179 templateCalls.push(
180 this.config.format.description
181 .replace( '$LANGUAGE', desc.language )
182 .replace( '$TEXT', desc.text )
183 );
184 }
185
186 return templateCalls.join( '\n' );
187 };
188
189 /**
190 * Fetches the wikitext for the categories to which the upload will
191 * be added.
192 *
193 * @private
194 * @return {string}
195 */
196 ForeignStructuredUpload.prototype.getCategories = function () {
197 var i, cat, categoryLinks = [];
198
199 if ( this.categories.length === 0 ) {
200 return this.config.format.uncategorized;
201 }
202
203 for ( i = 0; i < this.categories.length; i++ ) {
204 cat = this.categories[ i ];
205 categoryLinks.push( '[[Category:' + cat + ']]' );
206 }
207
208 return categoryLinks.join( '\n' );
209 };
210
211 /**
212 * Gets the wikitext for the license of the upload.
213 *
214 * @private
215 * @return {string}
216 */
217 ForeignStructuredUpload.prototype.getLicense = function () {
218 return this.config.format.license;
219 };
220
221 /**
222 * Get the source. This should be some sort of localised text for "Own work".
223 *
224 * @private
225 * @return {string}
226 */
227 ForeignStructuredUpload.prototype.getSource = function () {
228 return this.config.format.ownwork;
229 };
230
231 /**
232 * Get the username.
233 *
234 * @private
235 * @return {string}
236 */
237 ForeignStructuredUpload.prototype.getUser = function () {
238 var username, namespace;
239 // Do not localise, we don't know the language of target wiki
240 namespace = 'User';
241 username = mw.config.get( 'wgUserName' );
242 if ( !username ) {
243 // The user is not logged in locally. However, they might be logged in on the foreign wiki.
244 // We should record their username there. (If they're not logged in there either, this will
245 // record the IP address.) It's also possible that the user opened this dialog, got an error
246 // about not being logged in, logged in in another browser tab, then continued uploading.
247 username = '{{subst:REVISIONUSER}}';
248 }
249 return '[[' + namespace + ':' + username + '|' + username + ']]';
250 };
251
252 mw.ForeignStructuredUpload = ForeignStructuredUpload;
253 }( mediaWiki, jQuery, OO ) );