Bug 20489 Configure illegal file characters https://bugzilla.wikimedia.org/show_bug...
[mediawiki.git] / js2 / mwEmbed / libAddMedia / searchLibs / mediaWikiSearch.js
blobb1c14adb7e095510c7601a1c3eee5181b4bd0f17
1 var mediaWikiSearch = function( iObj ) {                
2         return this.init( iObj );
3 };
4 mediaWikiSearch.prototype = {
5         init:function( iObj ){
6                 //init base class and inherit: 
7                 var baseSearch = new baseRemoteSearch( iObj );
8                 for(var i in baseSearch){
9                         if(typeof this[i] =='undefined'){
10                                 this[i] = baseSearch[i];
11                         }else{
12                                 this['parent_'+i] =  baseSearch[i];
13                         }
14                 }
15                 //inherit the cp settings for 
16         },      
17         //returns a rObj by title 
18         addByTitle:function( title , callback){         
19                 js_log("AddByTitle::" + title);
20                 var _this = this;
21                 var reqObj = {
22                         'action':'query',
23                         'titles':'File:'+title, 
24                         'prop':'imageinfo|revisions|categories',
25                         'iiprop':'url|mime|size',
26                         'iiurlwidth': parseInt( this.rsd.thumb_width ),
27                         'rvprop':'content'      
28                 }
29                 do_api_req( {
30                         'data':reqObj, 
31                         'url':this.cp.api_url 
32                         }, function(data){                                              
33                                 callback( _this.addSingleResult(data) );                        
34                         }
35                 );                      
36         },
37         clearResults:function(){
38                 this.resultsObj = {};           
39                 this.last_query ='';
40         },
41         //update the resultObj with recently uploaded items by current User:
42         getUserRecentUploads:function(wgUser, callback){
43                 var _this = this;
44                 do_api_req({
45                         'data':{
46                                 'action':'query',
47                                 'list':'recentchanges',
48                                 'rcnamespace':6, //only files
49                                 'rcuser': wgUser,
50                                 'rclimit':15, //get last 15 uploaded files                              
51                         },
52                         'url':this.cp.api_url
53                 },function(data){                       
54                         var titleSet = {};
55                         var titleStr=''
56                         var pound='';
57                         //loop over the data and group by title
58                         if(data.query && data.query.recentchanges){     
59                                 for(var i in data.query.recentchanges){
60                                         var rc = data.query.recentchanges[i];
61                                         if( !titleSet[ rc.title ] ){
62                                                 titleSet[ rc.title ]=true;
63                                                 titleStr+= pound + rc.title;
64                                                 pound ='|';
65                                         }
66                                 }
67                         }                                       
68                         //now run the actual query ( too bad we cant use recentchanges as a gennerator
69                         do_api_req({
70                                 'data' : {
71                                         'action':'query',
72                                         'titles':titleStr,      
73                                         'prop':'imageinfo|revisions|categories',
74                                         'iiprop':'url|mime|size',
75                                         'iiurlwidth': parseInt( _this.rsd.thumb_width ),
76                                         'rvprop':'content'      
77                                 },
78                                 'url':_this.cp.api_url
79                         },function(data){                               
80                                 _this.clearResults();
81                                 _this.addResults(data);
82                                 if(callback)
83                                         callback();
84                         });                     
85                 });
86         },      
87         getSearchResults:function(){
88                 //call parent: 
89                 this.parent_getSearchResults();
90                 
91                 var _this = this;
92                 this.loading = true;
93                 js_log('f:getSearchResults for:' + $j('#rsd_q').val() );                
94                 //do two queries against the Image / File / MVD namespace:
95                                                                                  
96                 //build the image request object: 
97                 var reqObj = {
98                         'action':'query',                        
99                         'generator':'search',
100                         'gsrsearch':  $j('#rsd_q').val(),  
101                         'gsrnamespace':6, //(only search the "file" namespace (audio, video, images)
102                         'gsrwhat':'title',
103                         'gsrlimit':  this.cp.limit,
104                         'gsroffset': this.cp.offset,
105                         'prop':'imageinfo|revisions|categories',
106                         'iiprop':'url|mime|size',
107                         'iiurlwidth': parseInt( this.rsd.thumb_width ),
108                         'rvprop':'content'
109                 };                              
110                 //set up the number of request: 
111                 this.completed_req=0;
112                 this.num_req=1;         
113                 //setup the number of requests result flag:                                                                                      
114                 //also do a request for page titles (would be nice if api could query both at the same time) 
115                 reqObj['gsrwhat']='text';
116                 do_api_req( {
117                         'data':reqObj, 
118                         'url':this.cp.api_url 
119                         }, function(data){
120                                 js_log('mediaWikiSearch: got data response'); 
121                                 //parse the return data
122                                 _this.addResults( data);
123                                 //_this.checkRequestDone(); //only need if we do two queries one for title one for text
124                                 _this.loading = false;
125                 });                     
126         },      
127         //same as below but returns your rObj for convience
128         addSingleResult:function( data ){       
129                 return this.addResults(data, true);
130         },
131         addResults:function( data, returnFirst ){       
132                 js_log("f:addResults");
133                 var _this = this                
134                 //check if we have 
135                 if( typeof data['query-continue'] != 'undefined'){
136                         if( typeof data['query-continue'].search != 'undefined')
137                                 this.more_results = true;                       
138                 }
139                 //make sure we have pages to iderate:   
140                 if(data.query && data.query.pages){
141                         for(var page_id in  data.query.pages){
142                                 var page =  data.query.pages[ page_id ];
143                                 
144                                 //make sure the reop is shared (don't show for now it confusing things)
145                                 //@@todo support remote repository better
146                                 if( page.imagerepository == 'shared'){
147                                         continue;
148                                 }
149                                 
150                                 //make sure the page is not a redirect
151                                 if(page.revisions[0]['*'] && page.revisions[0]['*'].indexOf('#REDIRECT')===0){
152                                         //skip page is redirect 
153                                         continue;
154                                 }                                                               
155                                 //skip if its an empty or missing imageinfo: 
156                                 if( !page.imageinfo )
157                                         continue;
158                                 var rObj =      {
159                                         'id'             : page_id,
160                                         'titleKey'       : page.title,
161                                         'link'           : page.imageinfo[0].descriptionurl,                            
162                                         'title'          : page.title.replace(/File:|.jpg|.png|.svg|.ogg|.ogv|.oga/ig, ''),
163                                         'poster'         : page.imageinfo[0].thumburl,
164                                         'thumbwidth' : page.imageinfo[0].thumbwidth,
165                                         'thumbheight': page.imageinfo[0].thumbheight,
166                                         'orgwidth'       : page.imageinfo[0].width,
167                                         'orgheight'      : page.imageinfo[0].height,
168                                         'mime'           : page.imageinfo[0].mime,
169                                         'src'            : page.imageinfo[0].url,
170                                         'desc'           : page.revisions[0]['*'],              
171                                         //add pointer to parent search obj:
172                                         'pSobj'          :_this,                        
173                                         'meta':{
174                                                 'categories':page.categories
175                                         }
176                                 };                      
177                                 //attempt to parse out some stuff from the teplate: 
178                                 var desc = rObj.desc.match(/\|Description=(([^\n]*\n)*)\|Source=/)
179                                 if( desc && desc[1] ){                                  
180                                         rObj.desc = $j.trim( desc[1] );
181                                 }                                                                               
182                                 //likely a audio clip if no poster and type application/ogg 
183                                 //@@todo we should return audio/ogg for the mime type or some other way to specify its "audio" 
184                                 if( ! rObj.poster && rObj.mime == 'application/ogg' ){                                  
185                                         rObj.mime = 'audio/ogg';
186                                 }
187                                 //add to the resultObj
188                                 this.resultsObj[page_id] = rObj;
189                                 
190                                 //if returnFirst flag:
191                                 if(returnFirst)
192                                         return this.resultsObj[page_id];
193                                 
194                                 
195                                 this.num_results++;     
196                                 //for(var i in this.resultsObj[page_id]){
197                                 //      js_log('added: '+ i +' '+ this.resultsObj[page_id][i]);
198                                 //}
199                         }
200                 }else{
201                         js_log('no results:' + data);
202                 }       
203         },      
204         //check request done used for when we have multiple requests to check before formating results. 
205         checkRequestDone:function(){
206                 //display output if done: 
207                 this.completed_req++;
208                 if(this.completed_req == this.num_req){
209                         this.loading = 0;
210                 }
211         },      
212         getImageObj:function( rObj, size, callback ){                                   
213                 if( rObj.mime=='application/ogg' )
214                         return callback( {'url':rObj.src, 'poster' : rObj.url } );
215                 
216                 //we can just use direct request urls
217                 //@@todo thumb.php has some issues (cant serve the full image size, has poor erro handling etc) 
218                 /*var baseImgUrl = this.cp.api_url.replace('api.php', 'thumb.php'); 
219                 if ( rObj.mime=='image/jpeg' || rObj.mime=='image/png' ){
220                         //if requested size is greater than org size return reduced size obj: 
221                         if( size.width > rObj.orgwidth){
222                                 callback({ 
223                                                 'url'   : baseImgUrl + '?f=' + rObj.titleKey.replace(/\s/g, '_') + '&w='+ rObj.orgwidth,
224                                                 'width' : rObj.orgwidth,
225                                                 'height': rObj.orgheight
226                                 }); 
227                                 return false;
228                         }                       
229                 }
230                 //assuming svg or size is in range: give them requeted size
231                 callback({ 
232                                 'url'   : baseImgUrl + '?f=' + rObj.titleKey + '&w='+ size.width,
233                                 'width' : size.width,
234                                 'height': Math.round( ( rObj.orgheight / rObj.orgwidth)*size.width ) 
235                 }); 
236                 return false;
237                 */              
238                 
239                 //his could be depreciated if thumb.php improves
240                 var reqObj = {
241                         'action':'query',
242                         'format':'json',
243                         'titles':rObj.titleKey,
244                         'prop':'imageinfo',
245                         'iiprop':'url|size|mime' 
246                 }
247                 //set the width: 
248                 if(size.width)
249                         reqObj['iiurlwidth']= size.width;                                
250                  js_log('going to do req: ' + this.cp.api_url + ' ' + reqObj );
251                 do_api_req( {
252                         'data':reqObj, 
253                         'url' : this.cp.api_url
254                         }, function(data){                                                              
255                                 var imObj = {};
256                                 for(var page_id in  data.query.pages){
257                                         var iminfo =  data.query.pages[ page_id ].imageinfo[0];
258                                         //store the orginal width:                               
259                                         imObj['org_width']=iminfo.width;
260                                         //check if thumb size > than image size and is jpeg or png (it will not scale well above its max res)                           
261                                         if( ( iminfo.mime=='image/jpeg' || iminfo=='image/png' ) &&
262                                                 iminfo.thumbwidth > iminfo.width ){              
263                                                 imObj['url'] = iminfo.url;
264                                                 imObj['width'] = iminfo.width;
265                                                 imObj['height'] = iminfo.height;                                        
266                                         }else{                                  
267                                                 imObj['url'] = iminfo.thumburl;                                 
268                                                 imObj['width'] = iminfo.thumbwidth;
269                                                 imObj['height'] = iminfo.thumbheight;
270                                         }
271                                 }
272                                 js_log('getImageObj: get: ' + size.width + ' got url:' + imObj.url);                    
273                                 callback( imObj ); 
274                 });
275         },
276         //the insert image function   
277         insertImage:function( cEdit ){
278                 if(!cEdit)
279                         var cEdit = _this.cEdit;                
280         },
281         getEmbedHTML: function( rObj , options) {
282                 if(!options)
283                         options = {};
284                 //set up the output var with the default values: 
285                 var outOpt = { 'width': rObj.width, 'height': rObj.height};
286                 if( options['max_height'] ){                    
287                         outOpt.height = (options.max_height > rObj.height) ? rObj.height : options.max_height;  
288                         outOpt.width = (rObj.width / rObj.height) *outOpt.height;                       
289                 }                                               
290                 var style_attr = 'style="width:' + outOpt.width + 'px;height:' + outOpt.height +'px"';
291                 var id_attr = (options['id'])?' id = "' + options['id'] +'" ': '';
292                 var cat = rObj;         
293                 //return the html type: 
294                 if(rObj.mime.indexOf('image')!=-1){
295                         //if crop is null do base output: 
296                         var imgHtml = '<img ' + id_attr + ' src="' + rObj.edit_url  + '"' + style_attr + ' >';
297                         if( rObj.crop == null)
298                                 return imgHtml
299                         //else do crop output:  
300                                 return '<div style="width:'+rObj.crop.w +'px;height: ' + rObj.crop.h +'px;overflow:hidden;position:relative">' +
301                                                         '<div style="position:relative;top:-' + rObj.crop.y +'px;left:-' + rObj.crop.x +'px">'+
302                                                                 imgHtml + 
303                                                         '</div>'+
304                                                 '</div>';                       
305                 }
306                 var ahtml='';
307                 if(rObj.mime == 'application/ogg' || rObj.mime == 'audio/ogg'){
308                         ahtml = id_attr + 
309                                                 ' src="' + rObj.src + '" ' +
310                                                 style_attr +
311                                                 ' poster="'+  rObj.poster + '" '                                                                                
312                         if(rObj.mime.indexOf('application/ogg')!=-1){
313                                 return '<video ' + ahtml + '></video>'; 
314                         }
315                                         
316                         if(rObj.mime.indexOf('audio/ogg')!=-1){
317                                 return '<audio ' + ahtml + '></audio>';
318                         }
319                 }                                               
320                 js_log('ERROR:unsupored mime type: ' + rObj.mime);
321         },
322         getInlineDescWiki:function( rObj ){                                             
323                 var desc = this.parent_getInlineDescWiki( rObj );
324                 //just grab the description tag for inline desc:
325                 var descMatch = new RegExp(/Description=(\{\{en\|)?([^|]*|)/);                  
326                 var dparts = desc.match(descMatch);
327                                 
328                 if( dparts && dparts.length > 1){       
329                         desc = (dparts.length == 2) ? dparts[1] : dparts[2].replace('}}','');
330                         desc = (desc.substr(0,2) == '1=') ?desc.substr(2): desc;
331                         return desc;     
332                 }
333                 //else return the title since we could not find the desc:
334                 js_log('we could not find the Description tag in :' + desc );
335                 return rObj.title;
336         },
337         parseWikiTemplate: function( text ){
338                 //@@todo parse wiki Template return object with properties and values
339         },
340         //returns the inline wikitext for insertion (template based crops for now) 
341         getEmbedWikiCode: function( rObj ){             
342                         //set default layout to right justified
343                         var layout = ( rObj.layout)? rObj.layout:"right"
344                         //if crop is null do base output: 
345                         if( rObj.crop == null)
346                                 return this.parent_getEmbedWikiCode( rObj );                                                                                    
347                         //using the preview crop template: http://en.wikipedia.org/wiki/Template:Preview_Crop
348                         //@@todo should be replaced with server side cropping 
349                         return '{{Preview Crop ' + "\n" +
350                                                 '|Image   = ' + rObj.target_resource_title + "\n" +
351                                                 '|bSize   = ' + rObj.width + "\n" + 
352                                                 '|cWidth  = ' + rObj.crop.w + "\n" +
353                                                 '|cHeight = ' + rObj.crop.h + "\n" +
354                                                 '|oTop  = ' + rObj.crop.y + "\n" +
355                                                 '|oLeft   = ' + rObj.crop.x + "\n" +
356                                                 '|Location =' + layout + "\n" +
357                                                 '|Description =' + rObj.inlineDesc + "\n" +
358                                         '}}';
359         }