* $form = new HTMLForm( $someFields );
* $form->setMethod( 'get' )
* ->setWrapperLegendMsg( 'message-key' )
- * ->suppressReset()
* ->prepareForm()
- * ->displayForm();
+ * ->displayForm( '' );
* @endcode
* Note that you will have prepareForm and displayForm at the end. Other
* methods call done after that would simply not be part of the form :(
$this->mAction = $action;
return $this;
}
-
}
/**
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
*/
/**
* 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 ) {
$this->mLabel = wfMessage( $msg, $msgInfo )->parse();
} elseif ( isset( $params['label'] ) ) {
- $this->mLabel = $params['label'];
+ if ( $params['label'] === ' ' ) {
+ // Apparently some things set   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']}";
if ( isset( $params['flatlist'] ) ) {
$this->mClass .= ' mw-htmlform-flatlist';
}
+
+ if ( isset( $params['hidelabel'] ) ) {
+ $this->mShowEmptyLabels = false;
+ }
}
/**
$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',
}
function getLabel() {
- return $this->mLabel;
+ return is_null( $this->mLabel ) ? '' : $this->mLabel;
}
function getLabelHtml( $cellAttributes = array() ) {
$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() )
+ if ( $displayFormat === 'table' ) {
+ $html = Html::rawElement( 'td', array( 'class' => 'mw-label' ) + $cellAttributes,
+ Html::rawElement( 'label', $for, $labelValue )
);
- } elseif ( $displayFormat == 'div' ) {
- return Html::rawElement( 'div', array( 'class' => 'mw-label' ) + $cellAttributes,
- Html::rawElement( 'label', $for, $this->getLabel() )
- );
- } 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() {
}
}
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 ) {
* 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'];
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" );
}
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.
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;
+ }
}
/**
/**
* Multi-select field
*/
- class HTMLMultiSelectField extends HTMLFormField {
+ class HTMLMultiSelectField extends HTMLFormField implements HTMLNestedFilterable {
function validate( $value, $alldata ) {
$p = parent::validate( $value, $alldata );
}
}
+ 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;
}
* Add a submit button inline in the form (as opposed to
* HTMLForm::addButton(), which will add it at the end).
*/
-class HTMLSubmitField extends HTMLFormField {
+class HTMLSubmitField extends HTMLButtonField {
+ protected $buttonType = 'submit';
+}
+
+/**
+ * Adds a generic button inline to the form. Does not do anything, you must add
+ * click handling code in JavaScript. Use a HTMLSubmitField if you merely
+ * wish to add a submit button to a form.
+ *
+ * @since 1.22
+ */
+class HTMLButtonField extends HTMLFormField {
+ protected $buttonType = 'button';
public function __construct( $info ) {
$info['nodata'] = true;
public function getInputHTML( $value ) {
$attr = array(
'class' => 'mw-htmlform-submit ' . $this->mClass,
- 'name' => $this->mName,
'id' => $this->mID,
);
$attr['disabled'] = 'disabled';
}
- return Xml::submitButton( $value, $attr );
+ return Html::input(
+ $this->mName,
+ $value,
+ $this->buttonType,
+ $attr
+ );
}
protected function needsLabel() {
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 )
+ ) );
+ }
+ }
}
}
+ ## Make sure that form fields have their parent set. See bug 41337.
+ $dummyForm = new HTMLForm( array(), $context );
+
## Prod in defaults from the user
foreach ( $defaultPreferences as $name => &$info ) {
$prefFromUser = self::getOptionFromUser( $name, $info, $user );
$field = HTMLForm::loadInputFromParameters( $name, $info ); // For validation
+ $field->mParent = $dummyForm;
$defaultOptions = User::getDefaultOptions();
$globalDefault = isset( $defaultOptions[$name] )
? $defaultOptions[$name]
'label-message' => 'yourlanguage',
);
- /* see if there are multiple language variants to choose from*/
- $variantArray = array();
+ // see if there are multiple language variants to choose from
if ( !$wgDisableLangConversion ) {
$variants = $wgContLang->getVariants();
- foreach ( $variants as $v ) {
- $v = str_replace( '_', '-', strtolower( $v ) );
- $variantArray[$v] = $wgContLang->getVariantname( $v, false );
- }
+ if ( count( $variants ) > 1 ) {
+ $variantArray = array();
+ foreach ( $variants as $v ) {
+ $v = str_replace( '_', '-', strtolower( $v ) );
+ $variantArray[$v] = $wgContLang->getVariantname( $v, false );
+ }
- $options = array();
- foreach ( $variantArray as $code => $name ) {
- $display = wfBCP47( $code ) . ' - ' . $name;
- $options[$display] = $code;
- }
+ $options = array();
+ foreach ( $variantArray as $code => $name ) {
+ $display = wfBCP47( $code ) . ' - ' . $name;
+ $options[$display] = $code;
+ }
- if ( count( $variantArray ) > 1 ) {
$defaultPreferences['variant'] = array(
'label-message' => 'yourvariant',
'type' => 'select',
'section' => 'personal/i18n',
'help-message' => 'prefs-help-variant',
);
- }
- }
- if ( count( $variantArray ) > 1 && !$wgDisableLangConversion && !$wgDisableTitleConversion ) {
- $defaultPreferences['noconvertlink'] =
- array(
- 'type' => 'toggle',
- 'section' => 'personal/i18n',
- 'label-message' => 'tog-noconvertlink',
- );
+ if ( !$wgDisableTitleConversion ) {
+ $defaultPreferences['noconvertlink'] =
+ array(
+ 'type' => 'toggle',
+ 'section' => 'personal/i18n',
+ 'label-message' => 'tog-noconvertlink',
+ );
+ }
+ }
}
// show a preview of the old signature first
$disableEmailPrefs = false;
- $emailauthenticationclass = 'mw-email-not-authenticated';
if ( $wgEmailAuthentication ) {
+ $emailauthenticationclass = 'mw-email-not-authenticated';
if ( $user->getEmail() ) {
if ( $user->getEmailAuthenticationTimestamp() ) {
// date and time are separate parameters to facilitate localisation.
# Apply the same CSS class used on the input to the message:
'cssclass' => $emailauthenticationclass,
);
+ $defaultPreferences['emailaddress']['cssclass'] = $emailauthenticationclass;
}
- $defaultPreferences['emailaddress']['cssclass'] = $emailauthenticationclass;
if ( $wgEnableUserEmail && $user->isAllowed( 'sendemail' ) ) {
$defaultPreferences['disablemail'] = array(
'section' => 'rendering/advancedrendering',
'options' => $stubThresholdOptions,
'size' => 20,
- 'label' => $context->msg( 'stub-threshold' )->text(), // Raw HTML message. Yay?
+ 'label-raw' => $context->msg( 'stub-threshold' )->text(), // Raw HTML message. Yay?
);
if ( $wgAllowUserCssPrefs ) {
}
# Create preview link
- $mplink = htmlspecialchars( $mptitle->getLocalURL( "useskin=$skinkey" ) );
+ $mplink = htmlspecialchars( $mptitle->getLocalURL( array( 'useskin' => $skinkey ) ) );
$linkTools[] = "<a target='_blank' href=\"$mplink\">$previewtext</a>";
# Create links to user CSS/JS pages
}
/**
- * @deprecated in 1.19; will be removed in 1.20.
+ * @deprecated in 1.19
* @param $user User
* @return array
*/
}
/**
+ * Separate multi-option preferences into multiple preferences, since we
+ * have to store them separately
* @param $data array
* @return array
*/
function filterDataForSubmit( $data ) {
- // Support for separating multi-option preferences into multiple preferences
- // Due to lack of array support.
foreach ( $this->mFlatFields as $fieldname => $field ) {
- $info = $field->mParams;
-
- if ( $field instanceof HTMLMultiSelectField ) {
- $options = HTMLFormField::flattenOptions( $info['options'] );
+ if ( $field instanceof HTMLNestedFilterable ) {
+ $info = $field->mParams;
$prefix = isset( $info['prefix'] ) ? $info['prefix'] : $fieldname;
-
- foreach ( $options as $opt ) {
- $data["$prefix$opt"] = in_array( $opt, $data[$fieldname] );
+ foreach ( $field->filterDataForSubmit( $data[$fieldname] ) as $key => $value ) {
+ $data["$prefix-$key"] = $value;
}
-
- unset( $data[$fieldname] );
-
- } elseif ( $field instanceof HTMLCheckMatrix ) {
- $columns = HTMLFormField::flattenOptions( $info['columns'] );
- $rows = HTMLFormField::flattenOptions( $info['rows'] );
- $prefix = isset( $info['prefix'] ) ? $info['prefix'] : $fieldname;
- foreach ( $columns as $column ) {
- foreach ( $rows as $row ) {
- // Make sure option hasn't been removed
- if ( !isset( $info['remove-options'] )
- || !in_array( "$column-$row", $info['remove-options'] ) )
- {
- $data["$prefix-$column-$row"] = in_array( "$column-$row", $data[$fieldname] );
- }
- }
- }
-
unset( $data[$fieldname] );
}
}