summaryrefslogtreecommitdiff
path: root/includes/htmlform/HTMLForm.php
diff options
context:
space:
mode:
Diffstat (limited to 'includes/htmlform/HTMLForm.php')
-rw-r--r--includes/htmlform/HTMLForm.php185
1 files changed, 137 insertions, 48 deletions
diff --git a/includes/htmlform/HTMLForm.php b/includes/htmlform/HTMLForm.php
index ce140038..08fa0a91 100644
--- a/includes/htmlform/HTMLForm.php
+++ b/includes/htmlform/HTMLForm.php
@@ -51,6 +51,7 @@
* 'id' -- HTML id attribute
* 'cssclass' -- CSS class
* 'csshelpclass' -- CSS class used to style help text
+ * 'dir' -- Direction of the element.
* 'options' -- associative array mapping labels to values.
* Some field types support multi-level arrays.
* 'options-messages' -- associative array mapping message keys to values.
@@ -75,14 +76,35 @@
* '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()
+ * @see HTMLFormField::filter()
* 'validation-callback' -- a function name to give you the chance
* to impose extra validation on the field input.
- * @see HTMLForm::validate()
+ * @see HTMLFormField::validate()
* 'name' -- By default, the 'name' attribute of the input field
* is "wp{$fieldname}". If you want a different name
* (eg one without the "wp" prefix), specify it here and
* it will be used without modification.
+ * 'hide-if' -- expression given as an array stating when the field
+ * should be hidden. The first array value has to be the
+ * expression's logic operator. Supported expressions:
+ * 'NOT'
+ * [ 'NOT', array $expression ]
+ * To hide a field if a given expression is not true.
+ * '==='
+ * [ '===', string $fieldName, string $value ]
+ * To hide a field if another field identified by
+ * $field has the value $value.
+ * '!=='
+ * [ '!==', string $fieldName, string $value ]
+ * Same as [ 'NOT', [ '===', $fieldName, $value ]
+ * 'OR', 'AND', 'NOR', 'NAND'
+ * [ 'XXX', array $expression1, ..., array $expressionN ]
+ * To hide a field if one or more (OR), all (AND),
+ * neither (NOR) or not all (NAND) given expressions
+ * are evaluated as true.
+ * The expressions will be given to a JavaScript frontend
+ * module which will continually update the field's
+ * visibility.
*
* Since 1.20, you can chain mutators to ease the form generation:
* @par Example:
@@ -103,6 +125,7 @@ class HTMLForm extends ContextSource {
public static $typeMappings = array(
'api' => 'HTMLApiField',
'text' => 'HTMLTextField',
+ 'textwithbutton' => 'HTMLTextFieldWithButton',
'textarea' => 'HTMLTextAreaField',
'select' => 'HTMLSelectField',
'radio' => 'HTMLRadioField',
@@ -116,6 +139,7 @@ class HTMLForm extends ContextSource {
'selectorother' => 'HTMLSelectOrOtherField',
'selectandother' => 'HTMLSelectAndOtherField',
'namespaceselect' => 'HTMLSelectNamespace',
+ 'namespaceselectwithbutton' => 'HTMLSelectNamespaceWithButton',
'tagfilter' => 'HTMLTagFilter',
'submit' => 'HTMLSubmitField',
'hidden' => 'HTMLHiddenField',
@@ -129,6 +153,8 @@ class HTMLForm extends ContextSource {
'email' => 'HTMLTextField',
'password' => 'HTMLTextField',
'url' => 'HTMLTextField',
+ 'title' => 'HTMLTitleTextField',
+ 'user' => 'HTMLUserTextField',
);
public $mFieldData;
@@ -141,7 +167,7 @@ class HTMLForm extends ContextSource {
protected $mFieldTree;
protected $mShowReset = false;
protected $mShowSubmit = true;
- protected $mSubmitModifierClass = 'mw-ui-constructive';
+ protected $mSubmitFlags = array( 'constructive', 'primary' );
protected $mSubmitCallback;
protected $mValidationErrorMessage;
@@ -216,12 +242,12 @@ class HTMLForm extends ContextSource {
*/
protected $availableSubclassDisplayFormats = array(
'vform',
+ 'ooui',
);
/**
* Construct a HTMLForm object for given display type. May return a HTMLForm subclass.
*
- * @throws MWException When the display format requested is not known
* @param string $displayFormat
* @param mixed $arguments... Additional arguments to pass to the constructor.
* @return HTMLForm
@@ -234,6 +260,9 @@ class HTMLForm extends ContextSource {
case 'vform':
$reflector = new ReflectionClass( 'VFormHTMLForm' );
return $reflector->newInstanceArgs( $arguments );
+ case 'ooui':
+ $reflector = new ReflectionClass( 'OOUIHTMLForm' );
+ return $reflector->newInstanceArgs( $arguments );
default:
$reflector = new ReflectionClass( 'HTMLForm' );
$form = $reflector->newInstanceArgs( $arguments );
@@ -266,7 +295,10 @@ class HTMLForm extends ContextSource {
}
// Evil hack for mobile :(
- if ( !$this->getConfig()->get( 'HTMLFormAllowTableFormat' ) && $this->displayFormat === 'table' ) {
+ if (
+ !$this->getConfig()->get( 'HTMLFormAllowTableFormat' )
+ && $this->displayFormat === 'table'
+ ) {
$this->displayFormat = 'div';
}
@@ -405,7 +437,9 @@ class HTMLForm extends ContextSource {
* @throws MWException
* @return HTMLFormField Instance of a subclass of HTMLFormField
*/
- public static function loadInputFromParameters( $fieldname, $descriptor, HTMLForm $parent = null ) {
+ public static function loadInputFromParameters( $fieldname, $descriptor,
+ HTMLForm $parent = null
+ ) {
$class = static::getClassFromDescriptor( $fieldname, $descriptor );
$descriptor['fieldname'] = $fieldname;
@@ -677,6 +711,21 @@ class HTMLForm extends ContextSource {
}
/**
+ * Get header text.
+ *
+ * @param string|null $section The section to get the header text for
+ * @since 1.26
+ * @return string
+ */
+ function getHeaderText( $section = null ) {
+ if ( is_null( $section ) ) {
+ return $this->mHeader;
+ } else {
+ return isset( $this->mSectionHeaders[$section] ) ? $this->mSectionHeaders[$section] : '';
+ }
+ }
+
+ /**
* Add footer text, inside the form.
*
* @param string $msg Complete text of message to display
@@ -717,6 +766,21 @@ class HTMLForm extends ContextSource {
}
/**
+ * Get footer text.
+ *
+ * @param string|null $section The section to get the footer text for
+ * @since 1.26
+ * @return string
+ */
+ function getFooterText( $section = null ) {
+ if ( is_null( $section ) ) {
+ return $this->mFooter;
+ } else {
+ return isset( $this->mSectionFooters[$section] ) ? $this->mSectionFooters[$section] : '';
+ }
+ }
+
+ /**
* Add text to the end of the display.
*
* @param string $msg Complete text of message to display
@@ -834,14 +898,15 @@ class HTMLForm extends ContextSource {
# For good measure (it is the default)
$this->getOutput()->preventClickjacking();
$this->getOutput()->addModules( 'mediawiki.htmlform' );
+ $this->getOutput()->addModuleStyles( 'mediawiki.htmlform.styles' );
$html = ''
. $this->getErrors( $submitResult )
- . $this->mHeader
+ . $this->getHeaderText()
. $this->getBody()
. $this->getHiddenFields()
. $this->getButtons()
- . $this->mFooter;
+ . $this->getFooterText();
$html = $this->wrapForm( $html );
@@ -861,7 +926,6 @@ class HTMLForm extends ContextSource {
$attribs = array(
'action' => $this->getAction(),
'method' => $this->getMethod(),
- 'class' => array( 'visualClear' ),
'enctype' => $encType,
);
if ( !empty( $this->mId ) ) {
@@ -880,10 +944,11 @@ class HTMLForm extends ContextSource {
function wrapForm( $html ) {
# Include a <fieldset> wrapper for style, if requested.
if ( $this->mWrapperLegend !== false ) {
- $html = Xml::fieldset( $this->mWrapperLegend, $html );
+ $legend = is_string( $this->mWrapperLegend ) ? $this->mWrapperLegend : false;
+ $html = Xml::fieldset( $legend, $html );
}
- return Html::rawElement( 'form', $this->getFormAttributes(), $html );
+ return Html::rawElement( 'form', $this->getFormAttributes() + array( 'class' => 'visualClear' ), $html );
}
/**
@@ -940,7 +1005,10 @@ class HTMLForm extends ContextSource {
$attribs['class'] = array( 'mw-htmlform-submit' );
if ( $useMediaWikiUIEverywhere ) {
- array_push( $attribs['class'], 'mw-ui-button', $this->mSubmitModifierClass );
+ foreach ( $this->mSubmitFlags as $flag ) {
+ array_push( $attribs['class'], 'mw-ui-' . $flag );
+ }
+ array_push( $attribs['class'], 'mw-ui-button' );
}
$buttons .= Xml::submitButton( $this->getSubmitText(), $attribs ) . "\n";
@@ -1067,7 +1135,7 @@ class HTMLForm extends ContextSource {
* @since 1.24
*/
public function setSubmitDestructive() {
- $this->mSubmitModifierClass = 'mw-ui-destructive';
+ $this->mSubmitFlags = array( 'destructive', 'primary' );
}
/**
@@ -1075,7 +1143,7 @@ class HTMLForm extends ContextSource {
* @since 1.25
*/
public function setSubmitProgressive() {
- $this->mSubmitModifierClass = 'mw-ui-progressive';
+ $this->mSubmitFlags = array( 'progressive', 'primary' );
}
/**
@@ -1187,9 +1255,10 @@ class HTMLForm extends ContextSource {
* Prompt the whole form to be wrapped in a "<fieldset>", with
* this text as its "<legend>" element.
*
- * @param string|bool $legend HTML to go inside the "<legend>" element, or
- * false for no <legend>
- * Will be escaped
+ * @param string|bool $legend If false, no wrapper or legend will be displayed.
+ * If true, a wrapper will be displayed, but no legend.
+ * If a string, a wrapper will be displayed with that string as a legend.
+ * The string will be escaped before being output (this doesn't support HTML).
*
* @return HTMLForm $this for chaining calls (since 1.20)
*/
@@ -1263,11 +1332,14 @@ class HTMLForm extends ContextSource {
* @return HTMLForm $this for chaining calls (since 1.20)
*/
public function setMethod( $method = 'post' ) {
- $this->mMethod = $method;
+ $this->mMethod = strtolower( $method );
return $this;
}
+ /**
+ * @return string Always lowercase
+ */
public function getMethod() {
return $this->mMethod;
}
@@ -1291,7 +1363,7 @@ class HTMLForm extends ContextSource {
&$hasUserVisibleFields = false ) {
$displayFormat = $this->getDisplayFormat();
- $html = '';
+ $html = array();
$subsectionHtml = '';
$hasLabel = false;
@@ -1303,7 +1375,7 @@ class HTMLForm extends ContextSource {
$v = empty( $value->mParams['nodata'] )
? $this->mFieldData[$key]
: $value->getDefault();
- $html .= $value->$getFieldHtmlMethod( $v );
+ $html[] = $value->$getFieldHtmlMethod( $v );
$labelValue = trim( $value->getLabel() );
if ( $labelValue != '&#160;' && $labelValue !== '' ) {
@@ -1330,12 +1402,9 @@ class HTMLForm extends ContextSource {
$legend = $this->getLegend( $key );
- if ( isset( $this->mSectionHeaders[$key] ) ) {
- $section = $this->mSectionHeaders[$key] . $section;
- }
- if ( isset( $this->mSectionFooters[$key] ) ) {
- $section .= $this->mSectionFooters[$key];
- }
+ $section = $this->getHeaderText( $key ) .
+ $section .
+ $this->getFooterText( $key );
$attributes = array();
if ( $fieldsetIDPrefix ) {
@@ -1349,36 +1418,56 @@ class HTMLForm extends ContextSource {
}
}
- if ( $displayFormat !== 'raw' ) {
- $classes = array();
+ $html = $this->formatSection( $html, $sectionName, $hasLabel );
- if ( !$hasLabel ) { // Avoid strange spacing when no labels exist
- $classes[] = 'mw-htmlform-nolabel';
+ if ( $subsectionHtml ) {
+ if ( $this->mSubSectionBeforeFields ) {
+ return $subsectionHtml . "\n" . $html;
+ } else {
+ return $html . "\n" . $subsectionHtml;
}
+ } else {
+ return $html;
+ }
+ }
- $attribs = array(
- 'class' => implode( ' ', $classes ),
- );
+ /**
+ * Put a form section together from the individual fields' HTML, merging it and wrapping.
+ * @param array $fieldsHtml
+ * @param string $sectionName
+ * @param bool $anyFieldHasLabel
+ * @return string HTML
+ */
+ protected function formatSection( array $fieldsHtml, $sectionName, $anyFieldHasLabel ) {
+ $displayFormat = $this->getDisplayFormat();
+ $html = implode( '', $fieldsHtml );
- if ( $sectionName ) {
- $attribs['id'] = Sanitizer::escapeId( $sectionName );
- }
+ if ( $displayFormat === 'raw' ) {
+ return $html;
+ }
- if ( $displayFormat === 'table' ) {
- $html = Html::rawElement( 'table',
- $attribs,
- Html::rawElement( 'tbody', array(), "\n$html\n" ) ) . "\n";
- } elseif ( $displayFormat === 'inline' ) {
- $html = Html::rawElement( 'span', $attribs, "\n$html\n" );
- } else {
- $html = Html::rawElement( 'div', $attribs, "\n$html\n" );
- }
+ $classes = array();
+
+ if ( !$anyFieldHasLabel ) { // Avoid strange spacing when no labels exist
+ $classes[] = 'mw-htmlform-nolabel';
+ }
+
+ $attribs = array(
+ 'class' => implode( ' ', $classes ),
+ );
+
+ if ( $sectionName ) {
+ $attribs['id'] = Sanitizer::escapeId( $sectionName );
}
- if ( $this->mSubSectionBeforeFields ) {
- return $subsectionHtml . "\n" . $html;
+ if ( $displayFormat === 'table' ) {
+ return Html::rawElement( 'table',
+ $attribs,
+ Html::rawElement( 'tbody', array(), "\n$html\n" ) ) . "\n";
+ } elseif ( $displayFormat === 'inline' ) {
+ return Html::rawElement( 'span', $attribs, "\n$html\n" );
} else {
- return $html . "\n" . $subsectionHtml;
+ return Html::rawElement( 'div', $attribs, "\n$html\n" );
}
}