mediawiki.api: Correctly handle boolean parameters
authorBartosz Dziewoński <matma.rex@gmail.com>
Tue, 18 Aug 2015 17:01:34 +0000 (19:01 +0200)
committerBartosz Dziewoński <matma.rex@gmail.com>
Thu, 20 Aug 2015 15:46:21 +0000 (15:46 +0000)
Quoting https://www.mediawiki.org/w/api.php#main.2Fdatatypes:

    Boolean parameters work like HTML checkboxes: if the parameter is
    specified, regardless of value, it is considered true. For a false
    value, omit the parameter entirely.

Therefore, omit the parameters if the value is `false`.

The idea is adapted from MobileFrontend's api.js.

Change-Id: I596e14304951f49acc36159cb806b266117fb550

resources/src/mediawiki.api/mediawiki.api.js
tests/qunit/suites/resources/mediawiki.api/mediawiki.api.test.js

index 5e3a962..cae65c5 100644 (file)
@@ -49,7 +49,7 @@
         *         console.log( data );
         *     } );
         *
-        * Multiple values for a parameter can be specified using an array (since MW 1.25):
+        * Since MW 1.25, multiple values for a parameter can be specified using an array:
         *
         *     var api = new mw.Api();
         *     api.get( {
@@ -59,6 +59,9 @@
         *         console.log( data );
         *     } );
         *
+        * Since MW 1.26, boolean values for a parameter can be specified directly. If the value is
+        * `false` or `undefined`, the parameter will be omitted from the request, as required by the API.
+        *
         * @constructor
         * @param {Object} [options] See #defaultOptions documentation above. Can also be overridden for
         *  each individual request by passing them to #get or #post (or directly #ajax) later on.
                        return this.ajax( parameters, ajaxOptions );
                },
 
+               /**
+                * Massage parameters from the nice format we accept into a format suitable for the API.
+                *
+                * @private
+                * @param {Object} parameters (modified in-place)
+                */
+               preprocessParameters: function ( parameters ) {
+                       var key;
+                       // Handle common MediaWiki API idioms for passing parameters
+                       for ( key in parameters ) {
+                               // Multiple values are pipe-separated
+                               if ( $.isArray( parameters[key] ) ) {
+                                       parameters[key] = parameters[key].join( '|' );
+                               }
+                               // Boolean values are only false when not given at all
+                               if ( parameters[key] === false || parameters[key] === undefined ) {
+                                       delete parameters[key];
+                               }
+                       }
+               },
+
                /**
                 * Perform the API call.
                 *
                                delete parameters.token;
                        }
 
-                       for ( key in parameters ) {
-                               if ( $.isArray( parameters[key] ) ) {
-                                       parameters[key] = parameters[key].join( '|' );
-                               }
-                       }
+                       this.preprocessParameters( parameters );
 
                        // If multipart/form-data has been requested and emulation is possible, emulate it
                        if (
index de79198..26b6f57 100644 (file)
                api.get( { test: [ 'foo', 'bar', 'baz' ] } );
        } );
 
+       QUnit.test( 'Omitting false booleans', function ( assert ) {
+               QUnit.expect( 2 );
+               var api = new mw.Api();
+
+               this.server.respond( function ( request ) {
+                       assert.ok( !request.url.match( /foo/ ), 'foo query parameter is not present' );
+                       assert.ok( request.url.match( /bar=true/ ), 'bar query parameter is present with value true' );
+                       request.respond( 200, { 'Content-Type': 'application/json' }, '[]' );
+               } );
+
+               api.get( { foo: false, bar: true } );
+       } );
+
        QUnit.test( 'getToken() - cached', function ( assert ) {
                QUnit.expect( 2 );
                var api = new mw.Api();