http://www.mediawiki.org/wiki/Special:Code/MediaWiki/96133

Revision: 96133
Author:   salvatoreingala
Date:     2011-09-02 18:00:09 +0000 (Fri, 02 Sep 2011)
Log Message:
-----------
- Added 'required', 'minlength' and 'maxlength' options for 'list' type fields; 
added corresponding tests.
- Slightly changed the way 'required', 'minlength' and 'maxlength' options work 
in 'string' fields; added tests to cover some combinations of those params 
which were not tested.

Modified Paths:
--------------
    branches/salvatoreingala/Gadgets/Gadgets.i18n.php
    branches/salvatoreingala/Gadgets/Gadgets.php
    branches/salvatoreingala/Gadgets/Gadgets_tests.php
    branches/salvatoreingala/Gadgets/backend/GadgetPrefs.php
    branches/salvatoreingala/Gadgets/ui/resources/jquery.formBuilder.css
    branches/salvatoreingala/Gadgets/ui/resources/jquery.formBuilder.js

Modified: branches/salvatoreingala/Gadgets/Gadgets.i18n.php
===================================================================
--- branches/salvatoreingala/Gadgets/Gadgets.i18n.php   2011-09-02 17:51:16 UTC 
(rev 96132)
+++ branches/salvatoreingala/Gadgets/Gadgets.i18n.php   2011-09-02 18:00:09 UTC 
(rev 96133)
@@ -63,6 +63,9 @@
        'gadgets-formbuilder-date' => 'Please enter a valid date.',
        'gadgets-formbuilder-color' => 'Please enter a valid color.',
        'gadgets-formbuilder-scalar' => 'Valid values are true, false, null, a 
floating point number or a double quoted string.',
+       'gadgets-formbuilder-list-required' => 'Please create at least one 
item.',
+       'gadgets-formbuilder-list-minlength' => 'Please insert at least $1 
items.',
+       'gadgets-formbuilder-list-maxlength' => 'Please insert no more than $1 
items.',
        'gadgets-formbuilder-editor-ok' => 'OK',
        'gadgets-formbuilder-editor-cancel' => 'Cancel',
        'gadgets-formbuilder-editor-move-field' => 'Move this field',

Modified: branches/salvatoreingala/Gadgets/Gadgets.php
===================================================================
--- branches/salvatoreingala/Gadgets/Gadgets.php        2011-09-02 17:51:16 UTC 
(rev 96132)
+++ branches/salvatoreingala/Gadgets/Gadgets.php        2011-09-02 18:00:09 UTC 
(rev 96133)
@@ -92,7 +92,8 @@
        'messages'      => array(
                'gadgets-formbuilder-required', 
'gadgets-formbuilder-minlength', 'gadgets-formbuilder-maxlength',
                'gadgets-formbuilder-min', 'gadgets-formbuilder-max', 
'gadgets-formbuilder-integer', 'gadgets-formbuilder-date',
-               'gadgets-formbuilder-color', 'gadgets-formbuilder-scalar',
+               'gadgets-formbuilder-color', 
'gadgets-formbuilder-list-required', 'gadgets-formbuilder-list-minlength',
+               'gadgets-formbuilder-list-maxlength', 
'gadgets-formbuilder-scalar',
                'gadgets-formbuilder-editor-ok', 
'gadgets-formbuilder-editor-cancel', 'gadgets-formbuilder-editor-move-field',
                'gadgets-formbuilder-editor-delete-field', 
'gadgets-formbuilder-editor-edit-field', 
'gadgets-formbuilder-editor-edit-field-title', 
'gadgets-formbuilder-editor-insert-field',
                'gadgets-formbuilder-editor-chose-field', 
'gadgets-formbuilder-editor-chose-field-title', 
'gadgets-formbuilder-editor-create-field-title',

Modified: branches/salvatoreingala/Gadgets/Gadgets_tests.php
===================================================================
--- branches/salvatoreingala/Gadgets/Gadgets_tests.php  2011-09-02 17:51:16 UTC 
(rev 96132)
+++ branches/salvatoreingala/Gadgets/Gadgets_tests.php  2011-09-02 18:00:09 UTC 
(rev 96133)
@@ -274,7 +274,6 @@
                                        'label' => 'some label',
                                        'minlength' => 6,
                                        'maxlength' => 10,
-                                       'required' => false,
                                        'default' => 'default'
                                )
                        )
@@ -282,8 +281,23 @@
 
                $this->assertTrue( GadgetPrefs::isPrefsDescriptionValid( 
$correct ) );
 
-               //Tests with wrong default values
+               //Tests with wrong default values (when 'required' is not given)
                $wrong = $correct;
+               foreach ( array( null, '', true, false, 0, 1, array(), 'short', 
'veryverylongstring' ) as $def ) {
+                       $wrong['fields'][0]['default'] = $def;
+                       $this->assertFalse( 
GadgetPrefs::isPrefsDescriptionValid( $wrong ) );
+               }
+
+               //Tests with correct default values (when required is not given)
+               $correct2 = $correct;
+               foreach ( array( '6chars', '1234567890' ) as $def ) {
+                       $correct2['fields'][0]['default'] = $def;
+                       $this->assertTrue( 
GadgetPrefs::isPrefsDescriptionValid( $correct2 ) );
+               }
+
+               //Tests with wrong default values (when 'required' is false)
+               $wrong = $correct;
+               $wrong['fields'][0]['required'] = false;
                foreach ( array( null, true, false, 0, 1, array(), 'short', 
'veryverylongstring' ) as $def ) {
                        $wrong['fields'][0]['default'] = $def;
                        $this->assertFalse( 
GadgetPrefs::isPrefsDescriptionValid( $wrong ) );
@@ -291,16 +305,36 @@
 
                //Tests with correct default values (when required is false)
                $correct2 = $correct;
+               $correct2['fields'][0]['required'] = false;
                foreach ( array( '', '6chars', '1234567890' ) as $def ) {
                        $correct2['fields'][0]['default'] = $def;
                        $this->assertTrue( 
GadgetPrefs::isPrefsDescriptionValid( $correct2 ) );
                }
 
+               $correct = array(
+                       'fields' => array(
+                               array(
+                                       'name' => 'testString',
+                                       'type' => 'string',
+                                       'label' => 'some label',
+                                       'default' => ''
+                               )
+                       )
+               );
+
                //Test with empty default when "required" is true
+               $this->assertTrue( GadgetPrefs::isPrefsDescriptionValid( 
$correct ) );
+
+               //Test with empty default when "required" is true
                $wrong = $correct;
-               $wrong['fields']['testString']['required'] = true;
-               $wrong['fields']['testString']['default'] = '';
+               $wrong['fields'][0]['required'] = true;
                $this->assertFalse( GadgetPrefs::isPrefsDescriptionValid( 
$wrong ) );
+
+               //Test with empty default when "required" is false and 
minlength is given
+               $correct2 = $correct;
+               $correct2['fields'][0]['required'] = false;
+               $correct2['fields'][0]['minlength'] = 3;
+               $this->assertTrue( GadgetPrefs::isPrefsDescriptionValid( 
$correct2 ) );
        }
 
        //Tests for 'number' type preferences
@@ -707,6 +741,54 @@
                        )
                ) );
 
+
+               //Tests with 'minlength' and 'maxlength' options
+               $wrong = $correct;
+               $wrong['fields'][0]['minlength'] = 4;
+               $wrong['fields'][0]['maxlength'] = 3; //maxlength < minlength, 
wrong
+               $this->assertFalse( GadgetPrefs::isPrefsDescriptionValid( 
$wrong ) );
+               
+               $correct2 = $correct;
+               $correct2['fields'][0]['minlength'] = 2;
+               $correct2['fields'][0]['maxlength'] = 3;
+               $correct2['fields'][0]['default'] = array(
+                       array( 'bar' => true, 'car' => '#115599' ),
+                       array( 'bar' => false, 'car' => '#123456' )
+               );
+               $this->assertTrue( GadgetPrefs::isPrefsDescriptionValid( 
$correct2 ) );
+
+               $this->assertFalse( GadgetPrefs::checkPrefsAgainstDescription(
+                       $correct2,
+                       array( 'foo' => array( //less than minlength items
+                                       array( 'bar' => true, 'car' => 
'#115599' )
+                               )
+                       )
+               ) );
+
+               $this->assertFalse( GadgetPrefs::checkPrefsAgainstDescription(
+                       $correct2,
+                       array( 'foo' => array() ) //empty array, must fail 
because "required" is not false
+               ) );
+
+               $this->assertFalse( GadgetPrefs::checkPrefsAgainstDescription(
+                       $correct2,
+                       array( 'foo' => array( //more than minlength items
+                                       array( 'bar' => true, 'car' => 
'#115599' ),
+                                       array( 'bar' => false, 'car' => 
'#123456' ),
+                                       array( 'bar' => true, 'car' => 
'#ffffff' ),
+                                       array( 'bar' => false, 'car' => 
'#2357bd' )
+                               )
+                       )
+               ) );
+
+               //Test with 'required'
+               $correct2['fields'][0]['required'] = false;
+               $this->assertTrue( GadgetPrefs::checkPrefsAgainstDescription(
+                       $correct2,
+                       array( 'foo' => array() ) //empty array, must be 
accepted because "required" is false
+               ) );
+               
+               //Tests matchPrefsWithDescription
                $prefs = array( 'foo' => array(
                                array(
                                        'bar' => null,
@@ -723,6 +805,7 @@
                        )
                );
                
+               
                GadgetPrefs::matchPrefsWithDescription( $correct, $prefs );
                $this->assertTrue( GadgetPrefs::checkPrefsAgainstDescription( 
$correct, $prefs ) );
        }

Modified: branches/salvatoreingala/Gadgets/backend/GadgetPrefs.php
===================================================================
--- branches/salvatoreingala/Gadgets/backend/GadgetPrefs.php    2011-09-02 
17:51:16 UTC (rev 96132)
+++ branches/salvatoreingala/Gadgets/backend/GadgetPrefs.php    2011-09-02 
18:00:09 UTC (rev 96133)
@@ -254,6 +254,18 @@
                                ),
                                'default' => array(
                                        'isMandatory' => true
+                               ),
+                               'required' => array(
+                                       'isMandatory' => false,
+                                       'validator' => 'is_bool'
+                               ),
+                               'minlength' => array(
+                                       'isMandatory' => false,
+                                       'validator' => 'is_integer'
+                               ),
+                               'maxlength' => array(
+                                       'isMandatory' => false,
+                                       'validator' => 'is_integer'
                                )
                        ),
                        'validator' => 
'GadgetPrefs::validateListPrefDefinition',
@@ -406,6 +418,13 @@
                        return false;
                }
                
+               //Validate minlength and maxlength
+               $minlength = isset( $prefDefinition['minlength'] ) ? 
$prefDefinition['minlength'] : 0;
+               $maxlength = isset( $prefDefinition['maxlength'] ) ? 
$prefDefinition['maxlength'] : 1024;
+               if ( $minlength < 0 || $maxlength <= 0 || $minlength > 
$maxlength ) {
+                       return false;
+               }
+               
                //Check if the field definition is valid, apart from missing 
the name
                $itemDescription = $prefDefinition['field'];
                $itemDescription['name'] = 'dummy';
@@ -654,11 +673,13 @@
                $len = strlen( $value );
                
                //Checks the "required" option, if present
-               $required = isset( $prefDescription['required'] ) ? 
$prefDescription['required'] : true;
-               if ( $required === true && $len == 0 ) {
-                       return false;
-               } elseif ( $required === false && $len == 0 ) {
-                       return true; //overriding 'minlength'
+               if ( isset( $prefDescription['required'] ) ) {
+                       $required = isset( $prefDescription['required'] ) ? 
$prefDescription['required'] : true;
+                       if ( $required === true && $len == 0 ) {
+                               return false;
+                       } elseif ( $required === false && $len == 0 ) {
+                               return true; //overriding 'minlength', if given
+                       }
                }
                
                //Checks the "minlength" option, if present
@@ -803,6 +824,24 @@
                        return false;
                }
 
+               $nItems = count( $value );
+               
+               //Checks the "required" option, if present
+               if ( isset( $prefDescription['required'] ) ) {
+                       $required = $prefDescription['required'];
+                       if ( $required === true && $nItems == 0 ) {
+                               return false;
+                       } elseif ( $required === false && $nItems == 0 ) {
+                               return true; //overriding 'minlength'
+                       }
+               }
+
+               $minlength = isset( $prefDescription['minlength'] ) ? 
$prefDescription['minlength'] : 0;
+               $maxlength = isset( $prefDescription['maxlength'] ) ? 
$prefDescription['maxlength'] : 1024;
+               if ( $nItems < $minlength || $nItems > $maxlength ) {
+                       return false;
+               }
+
                $itemDescription = $prefDescription['field'];
                foreach ( $value as $item ) {
                        if ( !self::checkSinglePref( $itemDescription, array( 
'dummy' => $item ), 'dummy' ) ) {

Modified: branches/salvatoreingala/Gadgets/ui/resources/jquery.formBuilder.css
===================================================================
--- branches/salvatoreingala/Gadgets/ui/resources/jquery.formBuilder.css        
2011-09-02 17:51:16 UTC (rev 96132)
+++ branches/salvatoreingala/Gadgets/ui/resources/jquery.formBuilder.css        
2011-09-02 18:00:09 UTC (rev 96133)
@@ -80,8 +80,9 @@
        cursor: pointer;
 }
 
-.formbuilder-field-list {
+.formbuilder-list-items {
        border: 1px solid #888;
+       border-bottom: none;
 }
 
 .formbuilder-list-item-container {

Modified: branches/salvatoreingala/Gadgets/ui/resources/jquery.formBuilder.js
===================================================================
--- branches/salvatoreingala/Gadgets/ui/resources/jquery.formBuilder.js 
2011-09-02 17:51:16 UTC (rev 96132)
+++ branches/salvatoreingala/Gadgets/ui/resources/jquery.formBuilder.js 
2011-09-02 18:00:09 UTC (rev 96133)
@@ -198,7 +198,7 @@
        }, mw.msg( 'gadgets-formbuilder-scalar' ) );
 
        /* Functions used by the preferences editor */
-               function createFieldDialog( params, options ) {
+       function createFieldDialog( params, options ) {
                var self = this;
                
                if ( !$.isFunction( params.callback ) ) {
@@ -365,7 +365,7 @@
                } );
        }
 
-       function showEditFieldDialog( fieldDesc, options, callback ) {
+       function showEditFieldDialog( fieldDesc, listParams, options, callback 
) {
                $( { "fields": [ fieldDesc ] } )
                        .formBuilder( {
                                editable: true,
@@ -400,11 +400,14 @@
                                                        $( this ).dialog( 
"close" );
 
                                                        var ListField = 
validFieldTypes.list;
-                                                       callback( new 
ListField( {
-                                                                       type: 
'list',
-                                                                       name: 
name,
-                                                                       field: 
fieldDesc
-                                                               }, options ) );
+                                                       
+                                                       $.extend( listParams, {
+                                                               type: 'list',
+                                                               name: name,
+                                                               field: fieldDesc
+                                                       } );
+                                                       
+                                                       callback( new 
ListField( listParams, options ) );
                                                }
                                        },
                                        {
@@ -1722,9 +1725,26 @@
                                self._createItem( true );
                        } )
                        .appendTo( this.$div );
+               
+               //Add a hidden input to attach validation rules on the number 
of items
+               //We set its value to "" if there are no elements, or to the 
number of items otherwise
+               this._$hiddenInput = $( '<input/>').attr( {
+                               type: 'hidden',
+                               name: this.options.idPrefix + this.desc.name,
+                               id: this.options.idPrefix + this.desc.name
+                       } )
+                       .hide()
+                       .appendTo( this.$div );
+               
+               this._refreshHiddenField();
        }
        inherit( ListField, EmptyField );
 
+       ListField.prototype._refreshHiddenField = function() {
+               var nItems = this._$divItems.children().length;
+               this._$hiddenInput.val( nItems ? nItems : "" );
+       };
+
        ListField.prototype._createItem = function( afterInit, itemValue ) {
                var     itemDesc = $.extend( {}, this.desc.field, {
                                "name": this.desc.name
@@ -1763,7 +1783,7 @@
                var $itemButtons = $( '<div/>' )
                        .addClass( 'formbuilder-list-item-buttons' );
                
-
+               var self = this;
                $( '<span/>' )
                        .addClass( 'formbuilder-button 
formbuilder-list-button-delete ui-icon ui-icon-trash' )
                        .attr( 'title', mw.msg( 
'gadgets-formbuilder-editor-delete' ) )
@@ -1771,6 +1791,8 @@
                                $itemDiv.slideUp( function() {
                                        deleteFieldRules( itemField );
                                        $itemDiv.remove();
+                                       self._refreshHiddenField();
+                                       self._$hiddenInput.valid(); //force 
revalidation of the number of items
                                } );
                        } )
                        .appendTo( $itemButtons );
@@ -1791,6 +1813,9 @@
                                .slideDown();
 
                        addFieldRules( itemField );
+
+                       this._refreshHiddenField();
+                       this._$hiddenInput.valid(); //force revalidation of the 
number of items
                } else {
                        $itemDiv.appendTo( this._$divItems );
                }
@@ -1817,7 +1842,28 @@
        };
        
        ListField.prototype.getValidationSettings = function() {
-               var validationSettings = {};
+               var validationSettings = 
EmptyField.prototype.getValidationSettings.call( this );
+                       hiddenFieldRules = {}, hiddenFieldMessages = {};
+
+               if ( typeof this.desc.required != 'undefined' ) {
+                       hiddenFieldRules.required = this.desc.required;
+                       hiddenFieldMessages.required = mw.msg( 
'gadgets-formbuilder-list-required' );
+               }
+               
+               if ( typeof this.desc.minlength != 'undefined' ) {
+                       hiddenFieldRules.min = this.desc.minlength;
+                       hiddenFieldMessages.min = mw.msg( 
'gadgets-formbuilder-list-minlength', this.desc.minlength );
+               }
+
+               if ( typeof this.desc.maxlength == 'undefined' ) {
+                       this.desc.maxlength = 1024;
+               }
+               hiddenFieldRules.max = this.desc.maxlength;
+               hiddenFieldMessages.max = mw.msg( 
'gadgets-formbuilder-list-maxlength', this.desc.maxlength );
+
+               validationSettings.rules[this.options.idPrefix + 
this.desc.name] = hiddenFieldRules;
+               validationSettings.messages[this.options.idPrefix + 
this.desc.name] = hiddenFieldMessages;
+               
                this._$divItems.children().each( function( index, divItem ) {
                        var field = $( divItem ).data( 'field' );
                        $.extend( true, validationSettings, 
field.getValidationSettings() );
@@ -1931,9 +1977,23 @@
                        "builder": simpleFields.concat( [
                                {
                                        "name": "required",
-                                       "type": "boolean",
+                                       "type": "select",
                                        "label": "required",
-                                       "default": false
+                                       "default": null,
+                                       "options": [
+                                               {
+                                                       "name": "not specified",
+                                                       "value": null
+                                               },
+                                               {
+                                                       "name": "true",
+                                                       "value": true
+                                               },
+                                               {
+                                                       "name": "false",
+                                                       "value": false
+                                               }
+                                       ]
                                },
                                {
                                        "name": "minlength",
@@ -2088,23 +2148,64 @@
                                        }
                                } );
                                
-                               //Create the dialog to chose the field type
-                               var $form = $( {
-                                       fields: [ {
-                                               "name": "name",
-                                               "type": "string",
-                                               "label": "name",
-                                               "required": true,
-                                               "maxlength": 40,
-                                               "default": ""
-                                       },
-                                       {
-                                               "name": "type",
-                                               "type": "select",
-                                               "label": "type",
-                                               "options": selectOptions
-                                       } ]
-                               } ).formBuilder( { idPrefix: 'list-chose-type-' 
} )
+                               //Create the dialog to chose the field type and 
set list properties
+                               var description = {
+                                       "fields": [
+                                               {
+                                                       "name": "name",
+                                                       "type": "string",
+                                                       "label": "name",
+                                                       "required": true,
+                                                       "maxlength": 40,
+                                                       "default": ""
+                                               },
+                                               {
+                                                       "name": "required",
+                                                       "type": "select",
+                                                       "label": "required",
+                                                       "default": null,
+                                                       "options": [
+                                                               {
+                                                                       "name": 
"not specified",
+                                                                       
"value": null
+                                                               },
+                                                               {
+                                                                       "name": 
"true",
+                                                                       
"value": true
+                                                               },
+                                                               {
+                                                                       "name": 
"false",
+                                                                       
"value": false
+                                                               }
+                                                       ]
+                                               },
+                                               {
+                                                       "name": "minlength",
+                                                       "type": "number",
+                                                       "label": "minlength",
+                                                       "integer": true,
+                                                       "min": 0,
+                                                       "required": false,
+                                                       "default": null
+                                               },
+                                               {
+                                                       "name": "maxlength",
+                                                       "type": "number",
+                                                       "label": "maxlength",
+                                                       "integer": true,
+                                                       "min": 1,
+                                                       "required": false,
+                                                       "default": null
+                                               },
+                                               {
+                                                       "name": "type",
+                                                       "type": "select",
+                                                       "label": "type",
+                                                       "options": selectOptions
+                                               }
+                                       ]
+                               };
+                               var $form = $( description ).formBuilder( { 
idPrefix: 'list-chose-type-' } )
                                        .submit( function() {
                                                return false; //prevent form 
submission
                                        } );
@@ -2123,6 +2224,14 @@
                                                                click: 
function() {
                                                                        var 
values = $( this ).formBuilder( 'getValues' );
                                                                        $( this 
).dialog( "close" );
+
+                                                                       
//Remove properties that equal their default
+                                                                       $.each( 
description.fields, function( index, fieldSpec ) {
+                                                                               
var property = fieldSpec.name;
+                                                                               
if ( values[property] === fieldSpec['default'] ) {
+                                                                               
        delete values[property];
+                                                                               
}
+                                                                       } );
                                                                        
                                                                        var 
$dialog = $( this );
                                                                        
createFieldDialog( {
@@ -2132,7 +2241,7 @@
                                                                                
},
                                                                                
callback: function( field ) {
                                                                                
        $dialog.dialog( 'close' );
-                                                                               
        showEditFieldDialog( field.getDesc(), options, callback );
+                                                                               
        showEditFieldDialog( field.getDesc(), values, options, callback );
                                                                                
        return true;
                                                                                
}
                                                                        }, { 
editable: true } );


_______________________________________________
MediaWiki-CVS mailing list
[email protected]
https://lists.wikimedia.org/mailman/listinfo/mediawiki-cvs

Reply via email to