Fixed spacing and removed unneeded parenthesis
[lhc/web/wiklou.git] / includes / HTMLForm.php
index c08206d..7adbfc8 100644 (file)
@@ -1093,7 +1093,6 @@ class HTMLForm extends ContextSource {
                $this->mAction = $action;
                return $this;
        }
-
 }
 
 /**
@@ -1111,6 +1110,12 @@ abstract class HTMLFormField {
        protected $mClass = '';
        protected $mDefault;
 
+       /**
+        * @var bool If true will generate an empty div element with no label
+        * @since 1.22
+        */
+       protected $mShowEmptyLabels = true;
+
        /**
         * @var HTMLForm
         */
@@ -1203,6 +1208,8 @@ abstract class HTMLFormField {
        /**
         * Initialise the object
         * @param array $params Associative Array. See HTMLForm doc for syntax.
+        *
+        * @since 1.22 The 'label' attribute no longer accepts raw HTML, use 'label-raw' instead
         * @throws MWException
         */
        function __construct( $params ) {
@@ -1221,7 +1228,14 @@ abstract class HTMLFormField {
 
                        $this->mLabel = wfMessage( $msg, $msgInfo )->parse();
                } elseif ( isset( $params['label'] ) ) {
-                       $this->mLabel = $params['label'];
+                       if ( $params['label'] === ' ' ) {
+                               // Apparently some things set &nbsp directly and in an odd format
+                               $this->mLabel = ' ';
+                       } else {
+                               $this->mLabel = htmlspecialchars( $params['label'] );
+                       }
+               } elseif ( isset( $params['label-raw'] ) ) {
+                       $this->mLabel = $params['label-raw'];
                }
 
                $this->mName = "wp{$params['fieldname']}";
@@ -1266,6 +1280,10 @@ abstract class HTMLFormField {
                if ( isset( $params['flatlist'] ) ) {
                        $this->mClass .= ' mw-htmlform-flatlist';
                }
+
+               if ( isset( $params['hidelabel'] ) ) {
+                       $this->mShowEmptyLabels = false;
+               }
        }
 
        /**
@@ -1326,9 +1344,14 @@ abstract class HTMLFormField {
                $cellAttributes = array();
                $label = $this->getLabelHtml( $cellAttributes );
 
+               $outerDivClass = array(
+                       'mw-input',
+                       'mw-htmlform-nolabel' => ( $label === '' )
+               );
+
                $field = Html::rawElement(
                        'div',
-                       array( 'class' => 'mw-input' ) + $cellAttributes,
+                       array( 'class' => $outerDivClass ) + $cellAttributes,
                        $inputHtml . "\n$errors"
                );
                $html = Html::rawElement( 'div',
@@ -1457,7 +1480,7 @@ abstract class HTMLFormField {
        }
 
        function getLabel() {
-               return $this->mLabel;
+               return is_null( $this->mLabel ) ? '' : $this->mLabel;
        }
 
        function getLabelHtml( $cellAttributes = array() ) {
@@ -1469,20 +1492,32 @@ abstract class HTMLFormField {
                        $for['for'] = $this->mID;
                }
 
+               $labelValue = trim( $this->getLabel() );
+               $hasLabel = false;
+               if ( $labelValue !== ' ' && $labelValue !== '' ) {
+                       $hasLabel = true;
+               }
+
                $displayFormat = $this->mParent->getDisplayFormat();
-               $labelElement = Html::rawElement( 'label', $for, $this->getLabel() );
+               $html = '';
 
-               if ( $displayFormat == 'table' ) {
-                       return Html::rawElement( 'td', array( 'class' => 'mw-label' ) + $cellAttributes,
-                               Html::rawElement( 'label', $for, $this->getLabel() )
-                       );
-               } elseif ( $displayFormat == 'div' ) {
-                       return Html::rawElement( 'div', array( 'class' => 'mw-label' ) + $cellAttributes,
-                               Html::rawElement( 'label', $for, $this->getLabel() )
+               if ( $displayFormat === 'table' ) {
+                       $html = Html::rawElement( 'td', array( 'class' => 'mw-label' ) + $cellAttributes,
+                               Html::rawElement( 'label', $for, $labelValue )
                        );
-               } else {
-                       return $labelElement;
+               } elseif ( $hasLabel || $this->mShowEmptyLabels ) {
+                       if ( $displayFormat === 'div' ) {
+                               $html = Html::rawElement(
+                                       'div',
+                                       array( 'class' => 'mw-label' ) + $cellAttributes,
+                                       Html::rawElement( 'label', $for, $labelValue )
+                               );
+                       } else {
+                               $html = Html::rawElement( 'label', $for, $labelValue );
+                       }
                }
+
+               return $html;
        }
 
        function getDefault() {
@@ -1622,16 +1657,19 @@ class HTMLTextField extends HTMLFormField {
        }
 }
 class HTMLTextAreaField extends HTMLFormField {
+       const DEFAULT_COLS = 80;
+       const DEFAULT_ROWS = 25;
+
        function getCols() {
                return isset( $this->mParams['cols'] )
                        ? $this->mParams['cols']
-                       : 80;
+                       : static::DEFAULT_COLS;
        }
 
        function getRows() {
                return isset( $this->mParams['rows'] )
                        ? $this->mParams['rows']
-                       : 25;
+                       : static::DEFAULT_ROWS;
        }
 
        function getInputHTML( $value ) {
@@ -1806,9 +1844,33 @@ class HTMLCheckField extends HTMLFormField {
  * A checkbox matrix
  * Operates similarly to HTMLMultiSelectField, but instead of using an array of
  * options, uses an array of rows and an array of columns to dynamically
- * construct a matrix of options.
+ * construct a matrix of options. The tags used to identify a particular cell
+ * are of the form "columnName-rowName"
+ *
+ * Options:
+ *   columns:           Required list of columns in the matrix.
+ *   rows:              Required list of rows in the matrix.
+ *   force-options-on:  Accepts array of column-row tags to be displayed as enabled
+ *                      but unavailable to change
+ *   force-options-off: Accepts array of column-row tags to be displayed as disabled
+ *                      but unavailable to change.
  */
-class HTMLCheckMatrix extends HTMLFormField {
+class HTMLCheckMatrix extends HTMLFormField implements HTMLNestedFilterable {
+
+       static private $requiredParams = array(
+               // Required by underlying HTMLFormField
+               'fieldname',
+               // Required by HTMLCheckMatrix
+               'rows', 'columns'
+       );
+
+       public function __construct( $params ) {
+               $missing = array_diff( self::$requiredParams, array_keys( $params ) );
+               if ( $missing ) {
+                       throw HTMLFormFieldRequiredOptionsException::create( $this, $missing );
+               }
+               parent::__construct( $params );
+       }
 
        function validate( $value, $alldata ) {
                $rows = $this->mParams['rows'];
@@ -1872,23 +1934,25 @@ class HTMLCheckMatrix extends HTMLFormField {
                foreach ( $rows as $rowLabel => $rowTag ) {
                        $rowContents = Html::rawElement( 'td', array(), $rowLabel );
                        foreach ( $columns as $columnTag ) {
-                               // Knock out any options that are not wanted
-                               if ( isset( $this->mParams['remove-options'] )
-                                       && in_array( "$columnTag-$rowTag", $this->mParams['remove-options'] ) )
-                               {
-                                       $rowContents .= Html::rawElement( 'td', array(), ' ' );
-                               } else {
-                                       // Construct the checkbox
-                                       $thisAttribs = array(
-                                               'id' => "{$this->mID}-$columnTag-$rowTag",
-                                               'value' => $columnTag . '-' . $rowTag
-                                       );
-                                       $checkbox = Xml::check(
-                                               $this->mName . '[]',
-                                               in_array( $columnTag . '-' . $rowTag, (array)$value, true ),
-                                               $attribs + $thisAttribs );
-                                       $rowContents .= Html::rawElement( 'td', array(), $checkbox );
+                               $thisTag = "$columnTag-$rowTag";
+                               // Construct the checkbox
+                               $thisAttribs = array(
+                                       'id' => "{$this->mID}-$thisTag",
+                                       'value' => $thisTag,
+                               );
+                               $checked = in_array( $thisTag, (array)$value, true );
+                               if ( $this->isTagForcedOff( $thisTag ) ) {
+                                       $checked = false;
+                                       $thisAttribs['disabled'] = 1;
+                               } elseif ( $this->isTagForcedOn( $thisTag ) ) {
+                                       $checked = true;
+                                       $thisAttribs['disabled'] = 1;
                                }
+                               $rowContents .= Html::rawElement(
+                                       'td',
+                                       array(),
+                                       Xml::check( "{$this->mName}[]", $checked, $attribs + $thisAttribs )
+                               );
                        }
                        $tableContents .= Html::rawElement( 'tr', array(), "\n$rowContents\n" );
                }
@@ -1900,6 +1964,16 @@ class HTMLCheckMatrix extends HTMLFormField {
                return $html;
        }
 
+       protected function isTagForcedOff( $tag ) {
+               return isset( $this->mParams['force-options-off'] )
+                       && in_array( $tag, $this->mParams['force-options-off'] );
+       }
+
+       protected function isTagForcedOn( $tag ) {
+               return isset( $this->mParams['force-options-on'] )
+                       && in_array( $tag, $this->mParams['force-options-on'] );
+       }
+
        /**
         * Get the complete table row for the input, including help text,
         * labels, and whatever.
@@ -1964,6 +2038,27 @@ class HTMLCheckMatrix extends HTMLFormField {
                        return array();
                }
        }
+
+       function filterDataForSubmit( $data ) {
+               $columns = HTMLFormField::flattenOptions( $this->mParams['columns'] );
+               $rows = HTMLFormField::flattenOptions( $this->mParams['rows'] );
+               $res = array();
+               foreach ( $columns as $column ) {
+                       foreach ( $rows as $row ) {
+                               // Make sure option hasn't been forced
+                               $thisTag = "$column-$row";
+                               if ( $this->isTagForcedOff( $thisTag ) ) {
+                                       $res[$thisTag] = false;
+                               } elseif ( $this->isTagForcedOn( $thisTag ) ) {
+                                       $res[$thisTag] = true;
+                               } else {
+                                       $res[$thisTag] = in_array( $thisTag, $data );
+                               }
+                       }
+               }
+
+               return $res;
+       }
 }
 
 /**
@@ -2105,7 +2200,7 @@ class HTMLSelectOrOtherField extends HTMLTextField {
 /**
  * Multi-select field
  */
-class HTMLMultiSelectField extends HTMLFormField {
+class HTMLMultiSelectField extends HTMLFormField implements HTMLNestedFilterable {
 
        function validate( $value, $alldata ) {
                $p = parent::validate( $value, $alldata );
@@ -2198,6 +2293,17 @@ class HTMLMultiSelectField extends HTMLFormField {
                }
        }
 
+       function filterDataForSubmit( $data ) {
+               $options = HTMLFormField::flattenOptions( $this->mParams['options'] );
+
+               $res = array();
+               foreach ( $options as $opt ) {
+                       $res["$opt"] = in_array( $opt, $data );
+               }
+
+               return $res;
+       }
+
        protected function needsLabel() {
                return false;
        }
@@ -2653,3 +2759,22 @@ class HTMLApiField extends HTMLFormField {
                return '';
        }
 }
+
+interface HTMLNestedFilterable {
+       /**
+        * Support for seperating multi-option preferences into multiple preferences
+        * Due to lack of array support.
+        * @param $data array
+        */
+       function filterDataForSubmit( $data );
+}
+
+class HTMLFormFieldRequiredOptionsException extends MWException {
+       static public function create( HTMLFormField $field, array $missing ) {
+               return new self( sprintf(
+                       "Form type `%s` expected the following parameters to be set: %s",
+                       get_class( $field ),
+                       implode( ', ', $missing )
+               ) );
+       }
+}