diff options
Diffstat (limited to 'www/wiki/extensions/UploadWizard/resources/mw.DestinationChecker.js')
-rw-r--r-- | www/wiki/extensions/UploadWizard/resources/mw.DestinationChecker.js | 238 |
1 files changed, 238 insertions, 0 deletions
diff --git a/www/wiki/extensions/UploadWizard/resources/mw.DestinationChecker.js b/www/wiki/extensions/UploadWizard/resources/mw.DestinationChecker.js new file mode 100644 index 00000000..4e1af13d --- /dev/null +++ b/www/wiki/extensions/UploadWizard/resources/mw.DestinationChecker.js @@ -0,0 +1,238 @@ +( function ( mw, $ ) { + + mw.DestinationChecker = { + + api: new mw.Api(), + + // cached results from uniqueness api calls + cachedResult: {}, + cachedBlacklist: {}, + + /** + * Check title for validity. + * + * @param {string} title Title to check + * @return {jQuery.Promise} + * @return {Function} return.done + * @return {string} return.done.title The title that was passed in + * @return {Object|boolean} return.done.blacklist See #checkBlacklist + * @return {Object|boolean} return.done.unique See #checkUnique + */ + checkTitle: function ( title ) { + return $.when( + this.checkUnique( title ), + this.checkBlacklist( title ) + ).then( function ( unique, blacklist ) { + return { + unique: unique, + blacklist: blacklist, + title: title + }; + } ); + }, + + /** + * Async check if a title is in the titleblacklist. + * + * @param {string} title Title to check against the blacklist + * @return {jQuery.Promise} + * @return {Function} return.done + * @return {boolean} return.done.notBlacklisted + * @return {string} [return.done.blacklistReason] See mw.Api#isBlacklisted + * @return {string} [return.done.blacklistMessage] See mw.Api#isBlacklisted + * @return {string} [return.done.blacklistLine] See mw.Api#isBlacklisted + */ + checkBlacklist: function ( title ) { + var checker = this; + + /** + * Process result of a TitleBlacklist API call. + * + * @private + * @param {Object|boolean} blacklistResult `false` if not blacklisted, object if blacklisted + * @return {Object} + */ + function blacklistResultProcessor( blacklistResult ) { + var result; + + if ( blacklistResult === false ) { + result = { notBlacklisted: true }; + } else { + result = { + notBlacklisted: false, + blacklistReason: blacklistResult.reason, + blacklistMessage: blacklistResult.message, + blacklistLine: blacklistResult.line + }; + } + + checker.cachedBlacklist[ title ] = result; + return result; + } + + if ( this.cachedBlacklist[ title ] !== undefined ) { + return $.Deferred().resolve( this.cachedBlacklist[ title ] ); + } + + return mw.loader.using( 'mediawiki.api.titleblacklist' ).then( function () { + return checker.api.isBlacklisted( title ).then( blacklistResultProcessor ); + }, function () { + // it's not blacklisted, because the API isn't even available + return $.Deferred().resolve( { notBlacklisted: true, unavailable: true } ); + } ); + }, + + /** + * Async check if a filename is unique. Can be attached to a field's change() event + * This is a more abstract version of AddMedia/UploadHandler.js::doDestCheck + * + * @param {string} title Title to check for uniqueness + * @return {jQuery.Promise} + * @return {Function} return.done + * @return {boolean} return.done.isUnique + * @return {boolean} [return.done.isProtected] + * @return {Object} [return.done.img] Image info + * @return {string} [return.done.href] URL to file description page + */ + checkUnique: function ( title ) { + var checker = this, + NS_FILE = mw.config.get( 'wgNamespaceIds' ).file, + titleObj, prefix, ext; + + titleObj = mw.Title.newFromText( title ); + ext = mw.Title.normalizeExtension( titleObj.getExtension() || '' ); + // Strip namespace and file extension + prefix = titleObj.getNameText(); + + /** + * Process result of a an imageinfo API call. + * + * @private + * @param {Object} data API result + * @return {Object} + */ + function checkUniqueProcessor( data ) { + var result, protection, pageId, ntitle, ntitleObj, img; + + result = { isUnique: true }; + + if ( data.query && data.query.pages ) { + // The API will check for files with that filename. + // If no file found: a page with a key of -1 and no imageinfo + // If file found on another repository, such as when the wiki is using InstantCommons: page with a key of -1, plus imageinfo + // If file found on this repository: page with some positive numeric key + if ( data.query.pages[ -1 ] && !data.query.pages[ -1 ].imageinfo ) { + protection = data.query.pages[ -1 ].protection; + if ( protection && protection.length > 0 ) { + $.each( protection, function ( i, val ) { + if ( $.inArray( val.level, mw.config.get( 'wgUserGroups' ) ) === -1 ) { + result = { + isUnique: true, + isProtected: true + }; + } + } ); + } else { + // No conflict found on any repository this wiki uses + result = { isUnique: true }; + } + } else { + for ( pageId in data.query.pages ) { + if ( !data.query.pages.hasOwnProperty( pageId ) ) { + continue; + } + ntitle = data.query.pages[ pageId ].title; + ntitleObj = mw.Title.newFromText( ntitle ); + if ( ntitleObj.getNameText() !== prefix ) { + // It's a different file name entirely + continue; + } + if ( ext !== mw.Title.normalizeExtension( ntitleObj.getExtension() || '' ) ) { + // It's a different extension, that's fine (e.g. to upload a SVG version of a PNG file) + continue; + } + + // Conflict found, this filename is NOT unique + + if ( !data.query.pages[ pageId ].imageinfo ) { + // This means that there's a page, but it's not a file. Well, + // we should really report that anyway, but we shouldn't process + // it like a file, and we should defer to other entries that may be files. + result = { + isUnique: false, + title: ntitle, + img: null, + href: null + }; + continue; + } + + img = data.query.pages[ pageId ].imageinfo[ 0 ]; + + result = { + isUnique: false, + img: img, + title: ntitle, + href: img.descriptionurl + }; + + break; + } + } + } + + return result; + } + + if ( this.cachedResult[ title ] !== undefined ) { + return $.Deferred().resolve( this.cachedResult[ title ] ); + } + + // Setup the request -- will return thumbnail data if it finds one + // XXX do not use iiurlwidth as it will create a thumbnail + return $.when( + // Checks for exact matches on this wiki and foreign file repos + this.api.get( { + action: 'query', + titles: title, + prop: 'info|imageinfo', + inprop: 'protection', + iiprop: 'url|mime|size', + iiurlwidth: 150 + } ).then( checkUniqueProcessor ), + // Checks for matches with different versions of the file extension on this wiki only + this.api.get( { + action: 'query', + generator: 'allpages', + gapnamespace: NS_FILE, + gapprefix: prefix, + prop: 'info|imageinfo', + inprop: 'protection', + iiprop: 'url|mime|size', + iiurlwidth: 150 + } ).then( checkUniqueProcessor ) + ).then( function ( exact, fuzzy ) { + var result; + if ( !exact.isUnique || exact.isProtected ) { + result = exact; + } else if ( !fuzzy.isUnique || fuzzy.isProtected ) { + result = fuzzy; + } else { + result = { isUnique: true }; + } + + checker.cachedResult[ title ] = result; + return result; + } ); + }, + + /** + * Clears the result cache + */ + clearCache: function () { + this.cachedResult = {}; + } + + }; + +}( mediaWiki, jQuery ) ); |