removed output-disable in dbms-output fetching procedure
[mediawiki.git] / js2 / mwEmbed / libAddMedia / searchLibs / mediaWikiSearch.js
blob583fbc82c1d7355f4504cb924550b3c052da7dde
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, redirect_count ) {
19                 js_log( "AddByTitle::" + title );
20                 var _this = this;
21                 if ( !redirect_count )
22                         redirect_count = 0;
23                 if ( redirect_count > 5 ) {
24                         js_log( 'Error: addByTitle too many redirects' );
25                         callback( false );
26                         return false;
27                 }
28                 var reqObj = {
29                         'action':'query',
30                         'titles':'File:' + title,
31                         'prop':'imageinfo|revisions|categories',
32                         'iiprop':'url|mime|size',
33                         'iiurlwidth': parseInt( this.rsd.thumb_width ),
34                         'rvprop':'content'
35                 }
36                 do_api_req( {
37                         'data':reqObj,
38                         'url':this.cp.api_url
39                         }, function( data ) {
40                                 // check for redirect
41                                 for ( var i in data.query.pages ) {
42                                         var page = data.query.pages[i];
43                                         if ( page.revisions[0]['*'] && page.revisions[0]['*'].indexOf( '#REDIRECT' ) === 0 ) {
44                                                 var re = new RegExp( /[^\[]*\[\[([^\]]*)/ );
45                                                 var pt = page.revisions[0]['*'].match( re );
46                                                 if ( pt[1] ) {
47                                                         _this.addByTitle( pt[1], callback, redirect_count++ );
48                                                         return ;
49                                                 } else {
50                                                         js_log( 'Error: addByTitle could not proccess redirect' );
51                                                         callback( false );
52                                                         return false;
53                                                 }
54                                         }
55                                 }
56                                 // if not a redirect do the callback directly:  
57                                 callback( _this.addSingleResult( data ) );
58                         }
59                 );
60         },
61         clearResults:function() {
62                 this.resultsObj = { };
63                 this.last_query = '';
64         },
65         // update the resultObj with recently uploaded items by current User:
66         getUserRecentUploads:function( wgUser, callback ) {
67                 var _this = this;
68                 do_api_req( {
69                         'url':this.cp.api_url,
70                         'data': {
71                                 'action':'query',
72                                 'list':'recentchanges',
73                                 'rcnamespace':6, // only files
74                                 'rcuser': wgUser,
75                                 'rclimit':15 // get last 15 uploaded files                              
76                         }                       
77                 }, function( data ) {
78                         var titleSet = { };
79                         var titleStr = ''
80                         var pound = '';
81                         // loop over the data and group by title
82                         if ( data.query && data.query.recentchanges ) {
83                                 for ( var i in data.query.recentchanges ) {
84                                         var rc = data.query.recentchanges[i];
85                                         if ( !titleSet[ rc.title ] ) {
86                                                 titleSet[ rc.title ] = true;
87                                                 titleStr += pound + rc.title;
88                                                 pound = '|';
89                                         }
90                                 }
91                         }
92                         // now run the actual query ( too bad we can't use recentchanges as a generator )
93                         // bug 20563
94                         do_api_req( {
95                                 'data' : {
96                                         'action'        : 'query',
97                                         'titles'        : titleStr,
98                                         'prop'          : 'imageinfo|revisions|categories',
99                                         'iiprop'        : 'url|mime|size',
100                                         'iiurlwidth': parseInt( _this.rsd.thumb_width ),
101                                         'rvprop':'content'
102                                 },
103                                 'url':_this.cp.api_url
104                         }, function( data ) {
105                                 _this.clearResults();
106                                 _this.addResults( data );
107                                 if ( callback )
108                                         callback();
109                         } );
110                 } );
111         },
112         getSearchResults:function() {
113                 // Call parent: 
114                 this.parent_getSearchResults();
115                 // Set local ref:
116                 var _this = this;
117                                 
118                 js_log( 'f:getSearchResults for:' + $j( '#rsd_q' ).val() );
119                 // Do two queries against the Image / File / MVD namespace:
121                 // Build the image request object: 
122                 var reqObj = {
123                         'action':'query',
124                         'generator':'search',
125                         'gsrsearch':  $j( '#rsd_q' ).val(),
126                         'gsrnamespace':6, // (only search the "file" namespace (audio, video, images)
127                         'gsrwhat':'title',
128                         'gsrlimit':  this.cp.limit,
129                         'gsroffset': this.cp.offset,
130                         'prop':'imageinfo|revisions|categories',
131                         'iiprop':'url|mime|size',
132                         'iiurlwidth': parseInt( this.rsd.thumb_width ),
133                         'rvprop':'content'
134                 };
135                 // Set up the number of request: 
136                 this.completed_req = 0;
137                 this.num_req = 1;
138                 // Setup the number of requests result flag:                                                                                     
139                 // Also do a request for page titles (would be nice if api could query both at the same time) 
140                 reqObj['gsrwhat'] = 'text';
141                 do_api_req( {
142                         'data':reqObj,
143                         'url':this.cp.api_url
144                         }, function( data ) {
145                                 js_log( 'mediaWikiSearch: got data response' );
146                                 // parse the return data
147                                 _this.addResults( data );
148                                 // _this.checkRequestDone(); //only need if we do two queries one for title one for text
149                                 _this.loading = false;
150                 } );
151         },
152         // same as below but returns your rObj for convenience 
153         addSingleResult:function( data ) {
154                 return this.addResults( data, true );
155         },
156         addResults:function( data, returnFirst ) {
157                 js_log( "f:addResults" );
158                 var _this = this
159                 // check if we have 
160                 if ( typeof data['query-continue'] != 'undefined' ) {
161                         if ( typeof data['query-continue'].search != 'undefined' )
162                                 this.more_results = true;
163                 }
164                 // Make sure we have pages to idorate:  
165                 if ( data.query && data.query.pages ) {
166                         for ( var page_id in  data.query.pages ) {
167                                 var page =  data.query.pages[ page_id ];
168                                 
169                                 // Make sure the reop is shared (don't show for now it confusing things)
170                                 // @@todo support remote repository better
171                                 if ( page.imagerepository == 'shared' ) {
172                                         continue;
173                                 }
174                                 
175                                 // Make sure the page is not a redirect
176                                 if ( page.revisions && page.revisions[0] &&
177                                         page.revisions[0]['*'] && page.revisions[0]['*'].indexOf( '#REDIRECT' ) === 0 ) {
178                                         // skip page is redirect 
179                                         continue;
180                                 }
181                                 // Skip if its an empty or missing imageinfo: 
182                                 if ( !page.imageinfo )
183                                         continue;
184                                 var rObj =      {
185                                         'id'             : page_id,
186                                         'titleKey'       : page.title,
187                                         'link'           : page.imageinfo[0].descriptionurl,
188                                         'title'          : page.title.replace(/File:.jpg|.png|.svg|.ogg|.ogv|.oga/ig, ''),
189                                         'poster'         : page.imageinfo[0].thumburl,
190                                         'thumbwidth' : page.imageinfo[0].thumbwidth,
191                                         'thumbheight': page.imageinfo[0].thumbheight,
192                                         'orgwidth'       : page.imageinfo[0].width,
193                                         'orgheight'      : page.imageinfo[0].height,
194                                         'mime'           : page.imageinfo[0].mime,
195                                         'src'            : page.imageinfo[0].url,
196                                         'desc'           : page.revisions[0]['*'],
197                                         // add pointer to parent search obj:
198                                         'pSobj'          :_this,
199                                         'meta': {
200                                                 'categories':page.categories
201                                         }
202                                 };
203                                 /*
204                                  //to use once we get the wiki-text parser in shape
205                                 var pObj = mw.parser.pNew( rObj.desc );
206                                 //structured data on commons is based on the "information" template: 
207                                 var tmplInfo = pObj.templates( 'information' );         
208                                 rObj.desc = tmplInfo.description                
209                                 */
210                                 
211                                 // Attempt to parse out the description current user desc from the commons template: 
212                                 // @@todo these could be combined to a single regEx
213                                 // or better improve the wiki-text parsing and use above 
214                                 var desc = rObj.desc.match( /\|\s*description\s*=\s*(([^\n]*\n)*)\|\s*source=/i );
215                                 if ( desc && desc[1] ) {
216                                         rObj.desc = $j.trim( desc[1] );
217                                         // attempt to get the user language if set: 
218                                         if ( typeof wgUserLanguage != 'undefined' && wgUserLanguage ) {
219                                                 // for some reason the RegExp object is not happy:
220                                                 var reg = new RegExp( '\{\{\s*' + wgUserLanguage + '([^=]*)=([^\}]*)\}\}', 'gim' );
221                                                 var langMatch = reg.exec( rObj.desc );
222                                                 if ( langMatch && langMatch[2] ) {
223                                                         rObj.desc = langMatch[2];
224                                                 } else {
225                                                         // try simple lang template form:
226                                                         var reg = new RegExp( '\{\{\s*' + wgUserLanguage + '\\|([^\}]*)\}\}', 'gim' );
227                                                         var langMatch = reg.exec( rObj.desc );
228                                                         if ( langMatch && langMatch[1] ) {
229                                                                 rObj.desc = langMatch[1];
230                                                         }
231                                                 }
232                                         }
233                                 }
234                                                                                 
235                                 // Likely a audio clip if no poster and type application/ogg 
236                                 // @@todo we should return audio/ogg for the mime type or some other way to specify its "audio" 
237                                 if ( ! rObj.poster && rObj.mime == 'application/ogg' ) {
238                                         rObj.mime = 'audio/ogg';
239                                 }
240                                 // Add to the resultObj
241                                 this.resultsObj[page_id] = rObj;
242                                 
243                                 // If returnFirst flag:
244                                 if ( returnFirst )
245                                         return this.resultsObj[page_id];
246                                 
247                                 
248                                 this.num_results++;
249                                 // for(var i in this.resultsObj[page_id]){
250                                 //      js_log('added: '+ i +' '+ this.resultsObj[page_id][i]);
251                                 // }
252                         }
253                 } else {
254                         js_log( 'no results:' + data );
255                 }
256         },
257         // Check request done used for when we have multiple requests to check before formating results. 
258         checkRequestDone:function() {
259                 // Display output if done: 
260                 this.completed_req++;
261                 if ( this.completed_req == this.num_req ) {
262                         this.loading = 0;
263                 }
264         },
265         getImageObj:function( rObj, size, callback ) {
266                 if ( rObj.mime == 'application/ogg' )
267                         return callback( { 'url':rObj.src, 'poster' : rObj.url } );
268                 
269                 // This could be depreciated if thumb.php support is standard
270                 var reqObj = {
271                         'action':'query',
272                         'format':'json',
273                         'titles':rObj.titleKey,
274                         'prop':'imageinfo',
275                         'iiprop':'url|size|mime'
276                 }
277                 // Set the width: 
278                 if ( size.width )
279                         reqObj['iiurlwidth'] = size.width;
280                  js_log( 'going to do req: ' + this.cp.api_url + ' ' + reqObj );
281                 do_api_req( {
282                         'data':reqObj,
283                         'url' : this.cp.api_url
284                         }, function( data ) {
285                                 var imObj = { };
286                                 for ( var page_id in  data.query.pages ) {
287                                         var iminfo =  data.query.pages[ page_id ].imageinfo[0];
288                                         // store the orginal width:                              
289                                         imObj['org_width'] = iminfo.width;
290                                         // check if thumb size > than image size and is jpeg or png (it will not scale well above its max res)                          
291                                         if ( ( iminfo.mime == 'image/jpeg' || iminfo == 'image/png' ) &&
292                                                 iminfo.thumbwidth > iminfo.width ) {
293                                                 imObj['url'] = iminfo.url;
294                                                 imObj['width'] = iminfo.width;
295                                                 imObj['height'] = iminfo.height;
296                                         } else {
297                                                 imObj['url'] = iminfo.thumburl;
298                                                 imObj['width'] = iminfo.thumbwidth;
299                                                 imObj['height'] = iminfo.thumbheight;
300                                         }
301                                 }
302                                 js_log( 'getImageObj: get: ' + size.width + ' got url:' + imObj.url );
303                                 callback( imObj );
304                 } );
305         },
306         // the insert image function   
307         insertImage:function( cEdit ) {
308                 if ( !cEdit )
309                         var cEdit = _this.cEdit;
310         },      
311         getInlineDescWiki:function( rObj ) {
312                 var desc = this.parent_getInlineDescWiki( rObj );
313                 
314                 // Strip categories for inline Desc: (should strip license tags too but not as easy)
315                 desc = desc.replace( /\[\[Category\:[^\]]*\]\]/gi, '' );
316                 
317                 // Just grab the description tag for inline desc:
318                 var descMatch = new RegExp( /Description=(\{\{en\|)?([^|]*|)/ );
319                 var dparts = desc.match( descMatch );
320                                 
321                 if ( dparts && dparts.length > 1 ) {
322                         desc = ( dparts.length == 2 ) ? dparts[1] : dparts[2].replace( '}}', '' );
323                         desc = ( desc.substr( 0, 2 ) == '1=' ) ? desc.substr( 2 ): desc;
324                         return desc;
325                 }
326                 // Hackish attempt to strip templates
327                 desc = desc.replace( /\{\{[^\}]*\}\}/gi, '' );
328                 // strip any nexted template closures
329                 desc = desc.replace( /\}\}/gi, '' );
330                 // strip titles
331                 desc = desc.replace( /\=\=[^\=]*\=\=/gi, '' );
332                                 
333                 // else return the title since we could not find the desc:
334                 js_log( 'Error: No Description Tag, Using::' + desc );
335                 return desc;
336         },
337         // Returns the inline wikitext for insertion (template based crops for now) 
338         getEmbedWikiCode: function( rObj ) {
339                         // Set default layout to right justified
340                         var layout = ( rObj.layout ) ? rObj.layout:"right"
341                         // if crop is null do base output: 
342                         if ( rObj.crop == null )
343                                 return this.parent_getEmbedWikiCode( rObj );
344                         // Using the preview crop template: http://en.wikipedia.org/wiki/Template:Preview_Crop
345                         // @@todo should be replaced with server side cropping 
346                         return '{{Preview Crop ' + "\n" +
347                                                 '|Image   = ' + rObj.target_resource_title + "\n" +
348                                                 '|bSize   = ' + rObj.width + "\n" +
349                                                 '|cWidth  = ' + rObj.crop.w + "\n" +
350                                                 '|cHeight = ' + rObj.crop.h + "\n" +
351                                                 '|oTop  = ' + rObj.crop.y + "\n" +
352                                                 '|oLeft   = ' + rObj.crop.x + "\n" +
353                                                 '|Location =' + layout + "\n" +
354                                                 '|Description =' + rObj.inlineDesc + "\n" +
355                                         '}}';
356         }