From: jenkins-bot Date: Fri, 11 Sep 2015 20:45:53 +0000 (+0000) Subject: Merge "mediawiki.Title: Add normalizeExtension method" X-Git-Tag: 1.31.0-rc.0~10042 X-Git-Url: https://git.heureux-cyclage.org/?p=lhc%2Fweb%2Fwiklou.git;a=commitdiff_plain;h=cfd1345a482548b6e31f114d5267874bae47212b;hp=b2ba479ecadb5f0ea3030f3f04e18ab052cce796 Merge "mediawiki.Title: Add normalizeExtension method" --- diff --git a/includes/filerepo/file/File.php b/includes/filerepo/file/File.php index 3677a14b97..f40d216c58 100644 --- a/includes/filerepo/file/File.php +++ b/includes/filerepo/file/File.php @@ -213,14 +213,15 @@ abstract class File implements IDBAccessObject { } /** - * Normalize a file extension to the common form, and ensure it's clean. - * Extensions with non-alphanumeric characters will be discarded. + * Normalize a file extension to the common form, making it lowercase and checking some synonyms, + * and ensure it's clean. Extensions with non-alphanumeric characters will be discarded. + * Keep in sync with mw.Title.normalizeExtension() in JS. * - * @param string $ext (without the .) - * @return string + * @param string $extension File extension (without the leading dot) + * @return string File extension in canonical form */ - static function normalizeExtension( $ext ) { - $lower = strtolower( $ext ); + static function normalizeExtension( $extension ) { + $lower = strtolower( $extension ); $squish = array( 'htm' => 'html', 'jpeg' => 'jpg', diff --git a/resources/src/mediawiki/mediawiki.Title.js b/resources/src/mediawiki/mediawiki.Title.js index d1c5bb571a..14297b129a 100644 --- a/resources/src/mediawiki/mediawiki.Title.js +++ b/resources/src/mediawiki/mediawiki.Title.js @@ -493,7 +493,7 @@ * @return {mw.Title|null} A valid Title object or null if the input cannot be turned into a valid title */ Title.newFromUserInput = function ( title, defaultNamespace, options ) { - var namespace, m, id, ext, parts, normalizeExtension; + var namespace, m, id, ext, parts; // defaultNamespace is optional; check whether options moves up if ( arguments.length < 3 && $.type( defaultNamespace ) === 'object' ) { @@ -507,12 +507,6 @@ forUploading: true }, options ); - normalizeExtension = function ( extension ) { - // Remove only trailing space (that is removed by MW anyway) - extension = extension.toLowerCase().replace( /\s*$/, '' ); - return extension; - }; - namespace = defaultNamespace === undefined ? NS_MAIN : defaultNamespace; // Normalise whitespace and remove duplicates @@ -556,15 +550,14 @@ // Get the last part, which is supposed to be the file extension ext = parts.pop(); - // Does the supplied file name carry the desired file extension? - if ( options.fileExtension - && normalizeExtension( ext ) !== normalizeExtension( options.fileExtension ) - ) { - - // No, push back, whatever there was after the dot - parts.push( ext ); + if ( options.fileExtension ) { + // Does the supplied file name carry the desired file extension? + if ( Title.normalizeExtension( ext ) !== Title.normalizeExtension( options.fileExtension ) ) { + // No, push back, whatever there was after the dot + parts.push( ext ); + } - // And add the desired file extension later + // Always canonicalize to the desired file extension (e.g. 'jpeg' to 'jpg') ext = options.fileExtension; } @@ -743,6 +736,33 @@ } }; + /** + * Normalize a file extension to the common form, making it lowercase and checking some synonyms, + * and ensure it's clean. Extensions with non-alphanumeric characters will be discarded. + * Keep in sync with File::normalizeExtension() in PHP. + * + * @param {string} extension File extension (without the leading dot) + * @return {string} File extension in canonical form + */ + Title.normalizeExtension = function ( extension ) { + var + lower = extension.toLowerCase(), + squish = { + htm: 'html', + jpeg: 'jpg', + mpeg: 'mpg', + tiff: 'tif', + ogv: 'ogg' + }; + if ( squish.hasOwnProperty( lower ) ) { + return squish[ lower ]; + } else if ( /^[0-9a-z]+$/.test( lower ) ) { + return lower; + } else { + return ''; + } + }; + /* Public members */ Title.prototype = { diff --git a/tests/qunit/suites/resources/mediawiki/mediawiki.Title.test.js b/tests/qunit/suites/resources/mediawiki/mediawiki.Title.test.js index d5425a1064..af055beb16 100644 --- a/tests/qunit/suites/resources/mediawiki/mediawiki.Title.test.js +++ b/tests/qunit/suites/resources/mediawiki/mediawiki.Title.test.js @@ -487,12 +487,50 @@ } } ); - QUnit.test( 'newFromUserInput', 8, function ( assert ) { + QUnit.test( 'normalizeExtension', 5, function ( assert ) { + var extension, i, thisCase, prefix, + cases = [ + { + extension: 'png', + expected: 'png', + description: 'Extension already in canonical form' + }, + { + extension: 'PNG', + expected: 'png', + description: 'Extension lowercased in canonical form' + }, + { + extension: 'jpeg', + expected: 'jpg', + description: 'Extension changed in canonical form' + }, + { + extension: 'JPEG', + expected: 'jpg', + description: 'Extension lowercased and changed in canonical form' + }, + { + extension: '~~~', + expected: '', + description: 'Extension invalid and discarded' + } + ]; + + for ( i = 0; i < cases.length; i++ ) { + thisCase = cases[ i ]; + extension = mw.Title.normalizeExtension( thisCase.extension ); + + prefix = '[' + thisCase.description + '] '; + assert.equal( extension, thisCase.expected, prefix + 'Extension as expected' ); + } + } ); + + QUnit.test( 'newFromUserInput', 12, function ( assert ) { var title, i, thisCase, prefix, cases = [ { title: 'DCS0001557854455.JPG', - defaultNamespace: 0, options: { fileExtension: 'PNG' }, @@ -501,7 +539,6 @@ }, { title: 'MediaWiki:Msg-awesome', - defaultNamespace: undefined, expected: 'MediaWiki:Msg-awesome', description: 'Full title (page in MediaWiki namespace) supplied as string' }, @@ -519,6 +556,22 @@ }, expected: 'File:The/Mw/Sound.kml', description: 'Page in File-namespace without explicit options' + }, + { + title: 'File:Foo.JPEG', + options: { + fileExtension: 'jpg' + }, + expected: 'File:Foo.jpg', + description: 'Page in File-namespace with non-canonical extension' + }, + { + title: 'File:Foo.JPEG ', + options: { + fileExtension: 'jpg' + }, + expected: 'File:Foo.jpg', + description: 'Page in File-namespace with trailing whitespace' } ]; @@ -537,14 +590,14 @@ } } ); - QUnit.test( 'newFromFileName', 62, function ( assert ) { + QUnit.test( 'newFromFileName', 66, function ( assert ) { var title, i, thisCase, prefix, cases = [ { fileName: 'DCS0001557854455.JPG', typeOfName: 'Standard camera output', nameText: 'DCS0001557854455', - prefixedText: 'File:DCS0001557854455.JPG', + prefixedText: 'File:DCS0001557854455.jpg', extensionDesired: 'jpg' }, { @@ -557,7 +610,7 @@ fileName: 'Treppe 2222 Test upload.jpg', typeOfName: 'File name with spaces in it and lower case file extension', nameText: 'Treppe 2222 Test upload', - prefixedText: 'File:Treppe 2222 Test upload.jpg', + prefixedText: 'File:Treppe 2222 Test upload.JPG', extensionDesired: 'JPG' }, { @@ -654,6 +707,9 @@ assert.notStrictEqual( title, null, prefix + 'Parses successfully' ); assert.equal( title.getNameText(), thisCase.nameText, prefix + 'Filename matches original' ); assert.equal( title.getPrefixedText(), thisCase.prefixedText, prefix + 'File page title matches original' ); + if ( thisCase.extensionDesired !== undefined ) { + assert.equal( title.getExtension(), thisCase.extensionDesired, prefix + 'Extension matches desired' ); + } assert.equal( title.getNamespaceId(), 6, prefix + 'Namespace ID matches File namespace' ); } else { assert.strictEqual( title, null, thisCase.typeOfName + ', should not produce an mw.Title object' );