2 * MediaWiki Widgets - MediaResourceProvider class.
4 * @copyright 2011-2016 VisualEditor Team and others; see AUTHORS.txt
5 * @license The MIT License (MIT); see LICENSE.txt
10 * MediaWiki media resource provider.
13 * @extends mw.widgets.APIResultsProvider
16 * @param {string} apiurl The API url
17 * @param {Object} [config] Configuration options
18 * @cfg {string} [scriptDirUrl] The url of the API script
20 mw.widgets.MediaResourceProvider = function MwWidgetsMediaResourceProvider( apiurl, config ) {
21 config = config || {};
24 mw.widgets.MediaResourceProvider.super.call( this, apiurl, config );
26 // Fetching configuration
27 this.scriptDirUrl = config.scriptDirUrl;
28 this.isLocal = config.local !== undefined;
31 this.setAPIurl( mw.util.wikiScript( 'api' ) );
33 // If 'apiurl' is set, use that. Otherwise, build the url
34 // from scriptDirUrl and /api.php suffix
35 this.setAPIurl( this.getAPIurl() || ( this.scriptDirUrl + '/api.php' ) );
38 this.siteInfoPromise = null;
44 OO.inheritClass( mw.widgets.MediaResourceProvider, mw.widgets.APIResultsProvider );
51 mw.widgets.MediaResourceProvider.prototype.getStaticParams = function () {
55 mw.widgets.MediaResourceProvider.super.prototype.getStaticParams.call( this ),
58 iiprop: 'dimensions|url|mediatype|extmetadata|timestamp|user',
59 iiextmetadatalanguage: this.getLang(),
66 * Initialize the source and get the site info.
68 * Connect to the api url and retrieve the siteinfo parameters
69 * that are required for fetching results.
71 * @return {jQuery.Promise} Promise that resolves when the class
74 mw.widgets.MediaResourceProvider.prototype.loadSiteInfo = function () {
77 if ( !this.siteInfoPromise ) {
78 this.siteInfoPromise = new mw.Api().get( {
82 .then( function ( data ) {
83 provider.setImageSizes( data.query.general.imagelimits || [] );
84 provider.setThumbSizes( data.query.general.thumblimits || [] );
85 provider.setUserParams( {
86 // Standard width per resource
87 iiurlwidth: provider.getStandardWidth()
91 return this.siteInfoPromise;
95 * Override parent method and get results from the source
97 * @param {number} [howMany] The number of items to pull from the API
98 * @return {jQuery.Promise} Promise that is resolved into an array
99 * of available results, or is rejected if no results are available.
101 mw.widgets.MediaResourceProvider.prototype.getResults = function ( howMany ) {
106 return this.loadSiteInfo()
109 return $.Deferred().reject();
111 xhr = provider.fetchAPIresults( howMany );
115 function ( results ) {
116 if ( !results || results.length === 0 ) {
117 provider.toggleDepleted( true );
122 // Process failed, return an empty promise
124 provider.toggleDepleted( true );
125 return $.Deferred().resolve( [] );
128 .promise( { abort: function () {
137 * Get continuation API data
139 * @param {number} howMany The number of results to retrieve
140 * @return {Object} API request data
142 mw.widgets.MediaResourceProvider.prototype.getContinueData = function () {
147 * Set continuation data for the next page
149 * @param {Object} continueData Continuation data
151 mw.widgets.MediaResourceProvider.prototype.setContinue = function () {
157 * @param {Object[]} results API results
158 * @return {Object[]} Sorted results
160 mw.widgets.MediaResourceProvider.prototype.sort = function ( results ) {
165 * Call the API for search results.
167 * @param {number} howMany The number of results to retrieve
168 * @return {jQuery.Promise} Promise that resolves with an array of objects that contain
171 mw.widgets.MediaResourceProvider.prototype.fetchAPIresults = function ( howMany ) {
175 if ( !this.isValid() ) {
176 return $.Deferred().reject().promise( { abort: $.noop } );
179 api = this.isLocal ? new mw.Api() : new mw.ForeignApi( this.getAPIurl(), { anonymous: true } );
180 xhr = api.get( $.extend( {}, this.getStaticParams(), this.getUserParams(), this.getContinueData( howMany ) ) );
182 .then( function ( data ) {
183 var page, newObj, raw,
187 provider.toggleDepleted( true );
191 if ( data.continue ) {
192 // Update the offset for next time
193 provider.setContinue( data.continue );
195 // This is the last available set of results. Mark as depleted!
196 provider.toggleDepleted( true );
199 // If the source returned no results, it will not have a
202 raw = data.query.pages;
204 // Strip away the page ids
205 for ( page in raw ) {
206 if ( !raw[ page ].imageinfo ) {
207 // The search may give us pages that belong to the File:
208 // namespace but have no files in them, either because
209 // they were deleted or imported wrongly, or just started
210 // as pages. In that case, the response will not include
211 // imageinfo. Skip those files.
214 newObj = raw[ page ].imageinfo[ 0 ];
215 newObj.title = raw[ page ].title;
216 newObj.index = raw[ page ].index;
217 results.push( newObj );
221 return provider.sort( results );
223 .promise( { abort: xhr.abort } );
229 * @param {string} name
231 mw.widgets.MediaResourceProvider.prototype.setName = function ( name ) {
238 * @return {string} name
240 mw.widgets.MediaResourceProvider.prototype.getName = function () {
245 * Get standard width, based on the provider source's thumb sizes.
247 * @return {number|undefined} fetchWidth
249 mw.widgets.MediaResourceProvider.prototype.getStandardWidth = function () {
250 return ( this.thumbSizes && this.thumbSizes[ this.thumbSizes.length - 1 ] ) ||
251 ( this.imageSizes && this.imageSizes[ 0 ] ) ||
252 // Fall back on a number
259 * @return {string} prop
261 mw.widgets.MediaResourceProvider.prototype.getFetchProp = function () {
262 return this.fetchProp;
268 * @param {string} prop
270 mw.widgets.MediaResourceProvider.prototype.setFetchProp = function ( prop ) {
271 this.fetchProp = prop;
277 * @param {number[]} sizes Available thumbnail sizes
279 mw.widgets.MediaResourceProvider.prototype.setThumbSizes = function ( sizes ) {
280 this.thumbSizes = sizes;
286 * @param {number[]} sizes Available image sizes
288 mw.widgets.MediaResourceProvider.prototype.setImageSizes = function ( sizes ) {
289 this.imageSizes = sizes;
295 * @return {number[]} sizes Available thumbnail sizes
297 mw.widgets.MediaResourceProvider.prototype.getThumbSizes = function () {
298 return this.thumbSizes;
304 * @return {number[]} sizes Available image sizes
306 mw.widgets.MediaResourceProvider.prototype.getImageSizes = function () {
307 return this.imageSizes;
311 * Check if this source is valid.
313 * @return {boolean} Source is valid
315 mw.widgets.MediaResourceProvider.prototype.isValid = function () {
316 return this.isLocal ||
317 // If we don't have either 'apiurl' or 'scriptDirUrl'
318 // the source is invalid, and we will skip it
319 this.apiurl !== undefined ||
320 this.scriptDirUrl !== undefined;
322 }( jQuery, mediaWiki ) );