Improvements and fixes to HTMLForm:
authorHappy-melon <happy-melon@users.mediawiki.org>
Sat, 10 Apr 2010 12:03:30 +0000 (12:03 +0000)
committerHappy-melon <happy-melon@users.mediawiki.org>
Sat, 10 Apr 2010 12:03:30 +0000 (12:03 +0000)
* allow css classes to be specified in form descriptors
* Don't overwrite $field['name'] if it's set
* Allow IDs on hidden fields
* Enforce 'required' validation on Text fields
* Fix type validation on Int fields to correctly handle numbers larger than PHP_MAX_INT or with leading zeroes (eg phone numbers on 32 bit systems)
* Fix weak-typing error in MultiSelect field
* Formatting and doc fixes

includes/HTMLForm.php

index d51c290..e629155 100644 (file)
  * 
  *      'class'        -- the subclass of HTMLFormField that will be used
  *                                to create the object.  *NOT* the CSS class!
- *      'type'  -- roughly translates into the <select> type attribute.
+ *      'type'     -- roughly translates into the <select> type attribute.
  *                                if 'class' is not specified, this is used as a map
  *                                through HTMLForm::$typeMappings to get the class name.
  *      'default'  -- default value when the form is displayed
- *      'id'      -- HTML id attribute
+ *      'id'       -- HTML id attribute
+ *   'cssclass' -- CSS class
  *      'options'  -- varies according to the specific object.
  *      'label-message' -- message key for a message to use as the label.
  *                                can be an array of msg key and then parameters to 
@@ -35,7 +36,7 @@
  *                                the message.
  *      'required' -- passed through to the object, indicating that it
  *                                is a required field.
- *      'size'  -- the length of text fields
+ *      'size'     -- the length of text fields
  *      'filter-callback -- a function name to give you the chance to 
  *                                massage the inputted value before it's processed.
  *                                @see HTMLForm::filter()
@@ -111,14 +112,17 @@ class HTMLForm {
                $this->mFlatFields = array();
 
                foreach( $descriptor as $fieldname => $info ) {
-                       $section = '';
-                       if ( isset( $info['section'] ) )
-                               $section = $info['section'];
+                       $section = isset( $info['section'] ) 
+                               ? $info['section']
+                               : '';
 
-                       $info['name'] = $fieldname;
+                       $info['name'] = isset( $info['name'] )
+                               ? $info['name']
+                               : $fieldname;
 
-                       if ( isset( $info['type'] ) && $info['type'] == 'file' )
+                       if ( isset( $info['type'] ) && $info['type'] == 'file' ){
                                $this->mUseMultipart = true;
+                       }
 
                        $field = self::loadInputFromParameters( $info );
                        $field->mParent = $this;
@@ -219,8 +223,9 @@ class HTMLForm {
        function trySubmit() {
                # Check for validation
                foreach( $this->mFlatFields as $fieldname => $field ) {
-                       if ( !empty( $field->mParams['nodata'] ) )
+                       if ( !empty( $field->mParams['nodata'] ) ){
                                continue;
+                       }
                        if ( $field->validate( 
                                        $this->mFieldData[$fieldname],
                                        $this->mFieldData ) 
@@ -290,9 +295,10 @@ class HTMLForm {
         * Add a hidden field to the output
         * @param $name String field name
         * @param $value String field value
+        * @param $attribs Array
         */
-       public function addHiddenField( $name, $value ){
-               $this->mHiddenFields[ $name ] = $value;
+       public function addHiddenField( $name, $value, $attribs=array() ){
+               $this->mHiddenFields[ $name ] = array( $value, $attribs );
        }
        
        public function addButton( $name, $value, $id=null, $attribs=null ){
@@ -367,7 +373,8 @@ class HTMLForm {
                $html .= Html::hidden( 'title', $this->getTitle()->getPrefixedText() ) . "\n";
                
                foreach( $this->mHiddenFields as $name => $value ){
-                       $html .= Html::hidden( $name, $value ) . "\n";
+                       list( $value, $attribs ) = $value;
+                       $html .= Html::hidden( $name, $value, $attribs ) . "\n";
                }
 
                return $html;
@@ -592,8 +599,9 @@ class HTMLForm {
                $fieldData = array();
 
                foreach( $this->mFlatFields as $fieldname => $field ) {
-                       if ( !empty( $field->mParams['nodata'] ) ) continue;
-                       if ( !empty( $field->mParams['disabled'] ) ) {
+                       if ( !empty( $field->mParams['nodata'] ) ){
+                               continue;
+                       } elseif ( !empty( $field->mParams['disabled'] ) ) {
                                $fieldData[$fieldname] = $field->getDefault();
                        } else {
                                $fieldData[$fieldname] = $field->loadDataFromRequest( $wgRequest );
@@ -605,7 +613,7 @@ class HTMLForm {
                        $field = $this->mFlatFields[$name];
                        $value = $field->filter( $value, $this->mFlatFields );
                }
-
+               
                $this->mFieldData = $fieldData;
        }
 
@@ -642,6 +650,7 @@ abstract class HTMLFormField {
        public $mParams;
        protected $mLabel;      # String label.  Set on construction
        protected $mID;
+       protected $mClass = '';
        protected $mDefault;
        public $mParent;
        
@@ -660,7 +669,7 @@ abstract class HTMLFormField {
         * field input.  Don't forget to call parent::validate() to ensure
         * that the user-defined callback mValidationCallback is still run
         * @param $value String the value the field was submitted with
-        * @param $alldata $all the data collected from the form
+        * @param $alldata Array the data collected from the form
         * @return Mixed Bool true on success, or String error to display.
         */
        function validate( $value, $alldata ) {
@@ -749,6 +758,10 @@ abstract class HTMLFormField {
                        $this->mID = $id;
                }
 
+               if ( isset( $params['cssclass'] ) ) {
+                       $this->mClass = $params['cssclass'];
+               }
+
                if ( isset( $params['validation-callback'] ) ) {
                        $this->mValidationCallback = $params['validation-callback'];
                }
@@ -776,13 +789,19 @@ abstract class HTMLFormField {
                }
 
                $html = $this->getLabelHtml();
-               $html .= Html::rawElement( 'td', array( 'class' => 'mw-input' ),
-                                                       $this->getInputHTML( $value ) ."\n$errors" );
+               $html .= Html::rawElement( 
+                       'td', 
+                       array( 'class' => 'mw-input' ),
+                       $this->getInputHTML( $value ) ."\n$errors"
+               );
 
                $fieldType = get_class( $this );
 
-               $html = Html::rawElement( 'tr', array( 'class' => "mw-htmlform-field-$fieldType" ),
-                                                       $html ) . "\n";
+               $html = Html::rawElement( 
+                       'tr',
+                       array( 'class' => "mw-htmlform-field-$fieldType {$this->mClass}" ),
+                       $html 
+               ) . "\n";
 
                $helptext = null;
                if ( isset( $this->mParams['help-message'] ) ) {
@@ -929,6 +948,16 @@ class HTMLTextField extends HTMLFormField {
 
                return Html::element( 'input', $attribs );
        }
+       
+       public function validate( $value, $alldata ){
+               $p = parent::validate( $value, $alldata );
+               if( $p !== true ) return $p;
+               
+               if( isset( $this->mParams['required'] ) && $value === '' ){
+                       return wfMsgExt( 'htmlform-required', 'parseinline' );
+               }
+               return true;
+       }
 }
 class HTMLTextAreaField extends HTMLFormField {
        
@@ -1018,7 +1047,9 @@ class HTMLIntField extends HTMLFloatField {
 
                if ( $p !== true ) return $p;
 
-               if ( intval( $value ) != $value ) {
+               if ( $value !== '' 
+                       && ( !is_numeric( $value ) || round( $value ) != $value ) ) 
+               {
                        return wfMsgExt( 'htmlform-int-invalid', 'parse' );
                }
 
@@ -1223,7 +1254,7 @@ class HTMLMultiSelectField extends HTMLFormField {
                        } else {
                                $thisAttribs = array( 'id' => $this->mID . "-$info", 'value' => $info );
                                
-                               $checkbox = Xml::check( $this->mName . '[]', in_array( $info, $value ),
+                               $checkbox = Xml::check( $this->mName . '[]', $info === $value,
                                                                $attribs + $thisAttribs );
                                $checkbox .= '&nbsp;' . Html::rawElement( 'label', array( 'for' => $this->mID . "-$info" ), $label );
 
@@ -1352,9 +1383,14 @@ class HTMLInfoField extends HTMLFormField {
 class HTMLHiddenField extends HTMLFormField {
        
        public function getTableRow( $value ){
+               $params = array();
+               if( $this->mID ){
+                       $params['id'] = $this->mID;
+               }
                $this->mParent->addHiddenField( 
-                       $this->mParams['name'],
-                       $this->mParams['default']
+                       $this->mName,
+                       $this->mDefault,
+                       $params
                );
                return '';
        }