mediawiki.Title: Removing public setter functions. Title object should be immutable.
authorKrinkle <krinkle@users.mediawiki.org>
Tue, 2 Aug 2011 03:11:08 +0000 (03:11 +0000)
committerKrinkle <krinkle@users.mediawiki.org>
Tue, 2 Aug 2011 03:11:08 +0000 (03:11 +0000)
- To avoid repetition, instead of substituting, changed them to private helper functions
- Updated test suite to create new objects for different titles, rather than modifying the existing one.
- Adding missing unit tests, now 100% complete according to QUnit CompletnessTest
  + Test for Title.prototype.getNamespaceId
  + Test forTitle.prototype.getPrefixedText
  + Test forTitle.prototype.getExtension

Follows-up r90331 CR

resources/mediawiki/mediawiki.Title.js
tests/qunit/suites/resources/mediawiki/mediawiki.Title.js

index 3978d66..96292d2 100644 (file)
@@ -7,7 +7,7 @@
  *
  * Relies on: mw.config (wgFormattedNamespaces, wgNamespaceIds, wgCaseSensitiveNamespaces), mw.util.wikiGetlink
  */
-(function( $ ) {
+( function( $ ) {
 
        /* Local space */
 
@@ -26,15 +26,10 @@ var Title = function( title, namespace ) {
                        this._ext = null; // extension
 
                        if ( arguments.length === 2 ) {
-                               this.setNameAndExtension( title ).setNamespaceById( namespace );
+                               setNameAndExtension( this, title );
+                               this._ns = fixNsId( namespace );
                        } else if ( arguments.length === 1 ) {
-                               // If title is like "Blabla: Hello" ignore exception by setNamespace(),
-                               // and instead assume NS_MAIN and keep prefix
-                               try {
-                                       this.setAll( title );
-                               } catch(e) {
-                                       this.setNameAndExtension( title );
-                               }
+                               setAll( this, title );
                        }
                        return this;
        },
@@ -63,7 +58,100 @@ var Title = function( title, namespace ) {
                } else {
                        return '';
                }
+       },
+
+       /**
+        * Sanatize name.
+        */
+       fixName = function( s ) {
+               return clean( $.trim( s ) );
+       },
+
+       /**
+        * Sanatize name.
+        */
+       fixExt = function( s ) {
+               return clean( s.toLowerCase() );
+       },
+
+       /**
+        * Sanatize namespace id.
+        * @param id {Number} Namespace id.
+        * @return {Number|Boolean} The id as-is or boolean false if invalid.
+        */
+       fixNsId = function( id ) {
+               // wgFormattedNamespaces is an object of *string* key-vals (ie. arr["0"] not arr[0] )
+               var ns = mw.config.get( 'wgFormattedNamespaces' )[id.toString()];
+
+               // Check only undefined (may be false-y, such as '' (main namespace) ).
+               if ( ns === undefined ) {
+                       return false;
+               } else {
+                       return Number( id );
+               }
+       },
+
+       /**
+        * Get namespace id from namespace name by any known namespace/id pair (localized, canonical or alias).
+        *
+        * @example On a German wiki this would return 6 for any of 'File', 'Datei', 'Image' or even 'Bild'.
+        * @param ns {String} Namespace name (case insensitive, leading/trailing space ignored).
+        * @return {Number|Boolean} Namespace id or boolean false if unrecognized.
+        */
+       getNsIdByName = function( ns ) {
+               // toLowerCase throws exception on null/undefined. Return early.
+               if ( ns == null ) {
+                       return false;
+               }
+               ns = clean( $.trim( ns.toLowerCase() ) ); // Normalize
+               var id = mw.config.get( 'wgNamespaceIds' )[ns];
+               if ( id === undefined ) {
+                       mw.log( 'mw.Title: Unrecognized namespace: ' + ns );
+                       return false;
+               }
+               return fixNsId( id );
+       },
+
+       /**
+        * Helper to extract namespace, name and extension from a string.
+        *
+        * @param title {mw.Title}
+        * @param raw {String}
+        * @return {mw.Title}
+        */
+       setAll = function( title, s ) {
+               var     matches = s.match( /^(?:([^:]+):)?(.*?)(?:\.(\w{1,5}))?$/ );
+                       ns_match = getNsIdByName( matches[1] );
+               if ( matches.length && ns_match ) {
+                       if ( matches[1] ) { title._ns = ns_match; }
+                       if ( matches[2] ) { title._name = fixName( matches[2] ); }
+                       if ( matches[3] ) { title._ext = fixExt( matches[3] ); }
+               } else {
+                       // Consistency with MediaWiki: Unknown namespace > fallback to main namespace.
+                       title._ns = 0;
+                       setNameAndExtension( title, s );
+               }
+               return title;
+       },
+
+       /**
+        * Helper to extract name and extension from a string.
+        *
+        * @param title {mw.Title}
+        * @param raw {String}
+        * @return {mw.Title}
+        */
+       setNameAndExtension = function( title, raw ) {
+               var matches = raw.match( /^(?:)?(.*?)(?:\.(\w{1,5}))?$/ );
+               if ( matches.length ) {
+                       if ( matches[1] ) { title._name = fixName( matches[1] ); }
+                       if ( matches[2] ) { title._ext = fixExt( matches[2] ); }
+               } else {
+                       throw new Error( 'mw.Title: Could not parse title "' + raw + '"' );
+               }
+               return title;
        };
+        
 
        /* Static space */
 
@@ -118,37 +206,6 @@ var        Title = function( title, namespace ) {
 
        var fn = {
                constructor: Title,
-               /**
-                * @param id {Number} Canonical namespace id.
-                * @return {mw.Title} this
-                */
-               setNamespaceById: function( id ) {
-                       // wgFormattedNamespaces is an object of *string* key-vals,
-                       var ns = mw.config.get( 'wgFormattedNamespaces' )[id.toString()];
-
-                       // Cannot cast to boolean, ns may be '' (main namespace)
-                       if ( ns === undefined ) {
-                               this._ns = false;
-                       } else {
-                               this._ns = Number( id );
-                       }
-                       return this;
-               },
-
-               /**
-                * Set namespace by any known namespace/id pair (localized, canonical or alias)
-                * On a German wiki this could be 'File', 'Datei', 'Image' or even 'Bild' for NS_FILE.
-                * @param ns {String} A namespace name (case insensitive, space insensitive)
-                * @return {mw.Title} this
-                */
-               setNamespace: function( ns ) {
-                       ns = clean( $.trim( ns.toLowerCase() ) ); // Normalize
-                       var id = mw.config.get( 'wgNamespaceIds' )[ns];
-                       if ( id === undefined ) {
-                               throw new Error( 'mw.Title: Unrecognized canonical namespace: ' + ns );
-                       }
-                       return this.setNamespaceById( id );
-               },
 
                /**
                 * Get the namespace number.
@@ -167,16 +224,6 @@ var        Title = function( title, namespace ) {
                        return mw.config.get( 'wgFormattedNamespaces' )[this._ns].replace( / /g, '_' ) + (this._ns === 0 ? '' : ':');
                },
 
-               /**
-                * Set the "name" portion, removing illegal characters.
-                * @param s {String} Page name (without namespace prefix)
-                * @return {mw.Title} this
-                */
-               setName: function( s ) {
-                       this._name = clean( $.trim( s ) );
-                       return this;
-               },
-
                /**
                 * The name, like "Foo_bar"
                 * @return {String}
@@ -229,16 +276,6 @@ var        Title = function( title, namespace ) {
                        return text( this.getMain() );
                },
 
-               /**
-                * Set the "extension" portion, removing illegal characters.
-                * @param s {String}
-                * @return {mw.Title} this
-                */
-               setExtension: function( s ) {
-                       this._ext = clean( s.toLowerCase() );
-                       return this;
-               },
-
                /**
                 * Get the extension (returns null if there was none)
                 * @return {String|null} extension
@@ -255,37 +292,6 @@ var        Title = function( title, namespace ) {
                        return this._ext === null ? '' : '.' + this._ext;
                },
 
-               /**
-                * @param s {String}
-                * @return {mw.Title} this
-                */
-               setAll: function( s ) {
-                       var matches = s.match( /^(?:([^:]+):)?(.*?)(?:\.(\w{1,5}))?$/ );
-                       if ( matches.length ) {
-                               if ( matches[1] ) { this.setNamespace( matches[1] ); }
-                               if ( matches[2] ) { this.setName( matches[2] ); }
-                               if ( matches[3] ) { this.setExtension( matches[3] ); }
-                       } else {
-                               throw new Error( 'mw.Title: Could not parse title "' + s + '"' );
-                       }
-                       return this;
-               },
-
-               /**
-                * @param s {String}
-                * @return {mw.Title} this
-                */
-               setNameAndExtension: function( s ) {
-                       var matches = s.match( /^(?:)?(.*?)(?:\.(\w{1,5}))?$/ );
-                       if ( matches.length ) {
-                               if ( matches[1] ) { this.setName( matches[1] ); }
-                               if ( matches[2] ) { this.setExtension( matches[2] ); }
-                       } else {
-                               throw new Error( 'mw.Title: Could not parse title "' + s + '"' );
-                       }
-                       return this;
-               },
-
                /**
                 * Return the URL to this title
                 * @return {String}
index b873e7f..82a1ebc 100644 (file)
@@ -63,76 +63,56 @@ test( '-- Initial check', function() {
        ok( mw.Title, 'mw.Title defined' );
 });
 
-test( 'Filename', function() {
-       expect(4);
+test( 'Transform between Text and Db', function() {
+       expect(2);
        _titleConfig();
 
-       var title = new mw.Title( 'File:foo_bar.JPG' );
+       var title;
 
-       equal( title.getMain(), 'Foo_bar.jpg' );
-       equal( title.getMainText(), 'Foo bar.jpg' );
-       equal( title.getNameText(), 'Foo bar' );
-       equal( title.toString(), 'File:Foo_bar.jpg' );
+       title = new mw.Title( 'File:quux pif.jpg' );
+       equal( title.getName(), 'Quux_pif' );
+
+       title = new mw.Title( 'File:Glarg_foo_glang.jpg' );
+       equal( title.getNameText(), 'Glarg foo glang' );
 });
 
-test( 'Transform between Text to Db', function() {
-       expect(6);
+test( 'Main text for filename', function() {
+       expect(8);
        _titleConfig();
 
        var title = new mw.Title( 'File:foo_bar.JPG' );
-       title.setName( 'quux pif' );
-
-       equal( title.getMain(), 'Quux_pif.jpg' );
-       equal( title.getMainText(), 'Quux pif.jpg' );
-       equal( title.getNameText(), 'Quux pif' );
-       equal( title.toString(), 'File:Quux_pif.jpg' );
 
-       title.setName( 'glarg_foo_glang' );
-
-       equal( title.toString(), 'File:Glarg_foo_glang.jpg' );
-       equal( title.getMainText(), 'Glarg foo glang.jpg' );
-});
-
-test( 'Initiate from name and set namespace', function() {
-       expect(1);
-       _titleConfig();
-
-       var title = new mw.Title( 'catalonian_penguins.PNG' );
-       title.setNamespace( 'file' );
-       equal( title.toString(), 'File:Catalonian_penguins.png' );
+       equal( title.getNamespaceId(), 6 );
+       equal( title.getNamespacePrefix(), 'File:' );
+       equal( title.getName(), 'Foo_bar' );
+       equal( title.getNameText(), 'Foo bar' );
+       equal( title.getMain(), 'Foo_bar.jpg' );
+       equal( title.getMainText(), 'Foo bar.jpg' );
+       equal( title.getExtension(), 'jpg' );
+       equal( title.getDotExtension(), '.jpg' );
 });
 
 test( 'Namespace detection and conversion', function() {
-       expect(7);
+       expect(6);
        _titleConfig();
 
        var title;
 
-       title = new mw.Title( 'something.PDF' );
-       title.setNamespace( 'file' );
+       title = new mw.Title( 'something.PDF', 6 );
        equal( title.toString(), 'File:Something.pdf' );
 
-       title = new mw.Title( 'NeilK' );
-       title.setNamespace( 'user_talk' );
+       title = new mw.Title( 'NeilK', 3 );
        equal( title.toString(), 'User_talk:NeilK' );
        equal( title.toText(), 'User talk:NeilK' );
 
-       title = new mw.Title( 'Frobisher' );
-       title.setNamespaceById( 100 );
+       title = new mw.Title( 'Frobisher', 100 );
        equal( title.toString(), 'Penguins:Frobisher' );
 
-       title = new mw.Title( 'flightless_yet_cute.jpg' );
-       title.setNamespace( 'antarctic_waterfowl' );
+       title = new mw.Title( 'antarctic_waterfowl:flightless_yet_cute.jpg' );
        equal( title.toString(), 'Penguins:Flightless_yet_cute.jpg' );
 
-       title = new mw.Title( 'flightless_yet_cute.jpg' );
-       title.setNamespace( 'Penguins' );
+       title = new mw.Title( 'Penguins:flightless_yet_cute.jpg' );
        equal( title.toString(), 'Penguins:Flightless_yet_cute.jpg' );
-
-       title = new mw.Title( 'flightless_yet_cute.jpg' );
-       raises( function() {
-               title.setNamespace( 'Entirely Unknown' );
-       });
 });
 
 test( 'Case-sensivity', function() {
@@ -157,6 +137,16 @@ test( 'Case-sensivity', function() {
        equal( title.toString(), 'User:John', '$wgCapitalLinks=false: User namespace is insensitive, first-letter becomes uppercase' );
 });
 
+test( 'toString / toText', function() {
+       expect(2);
+       _titleConfig();
+
+       var title = new mw.Title( 'Some random page' );
+
+       equal( title.toString(), title.getPrefixedDb() );
+       equal( title.toText(), title.getPrefixedText() );
+});
+
 test( 'Exists', function() {
        expect(3);
        _titleConfig();