* Some field types support multi-level arrays.
* 'options-messages' -- associative array mapping message keys to values.
* Some field types support multi-level arrays.
- * 'options-message' -- message key to be parsed to extract the list of
+ * 'options-message' -- message key or object to be parsed to extract the list of
* options (like 'ipbreason-dropdown').
- * 'label-message' -- message key for a message to use as the label.
+ * 'label-message' -- message key or object for a message to use as the label.
* can be an array of msg key and then parameters to
* the message.
* 'label' -- alternatively, a raw text message. Overridden by
* label-message
* 'help' -- message text for a message to use as a help text.
- * 'help-message' -- message key for a message to use as a help text.
+ * 'help-message' -- message key or object for a message to use as a help text.
* can be an array of msg key and then parameters to
* the message.
* Overwrites 'help-messages' and 'help'.
- * 'help-messages' -- array of message key. As above, each item can
+ * 'help-messages' -- array of message keys/objects. As above, each item can
* be an array of msg key and then parameters.
* Overwrites 'help'.
* 'required' -- passed through to the object, indicating that it
* is a required field.
* 'size' -- the length of text fields
- * 'filter-callback -- a function name to give you the chance to
+ * 'filter-callback' -- a function name to give you the chance to
* massage the inputted value before it's processed.
* @see HTMLFormField::filter()
* 'validation-callback' -- a function name to give you the chance
*/
class HTMLForm extends ContextSource {
// A mapping of 'type' inputs onto standard HTMLFormField subclasses
- public static $typeMappings = array(
+ public static $typeMappings = [
'api' => 'HTMLApiField',
'text' => 'HTMLTextField',
'textwithbutton' => 'HTMLTextFieldWithButton',
'url' => 'HTMLTextField',
'title' => 'HTMLTitleTextField',
'user' => 'HTMLUserTextField',
- );
+ ];
public $mFieldData;
protected $mFieldTree;
protected $mShowReset = false;
protected $mShowSubmit = true;
- protected $mSubmitFlags = array( 'constructive', 'primary' );
+ protected $mSubmitFlags = [ 'constructive', 'primary' ];
protected $mSubmitCallback;
protected $mValidationErrorMessage;
protected $mPre = '';
protected $mHeader = '';
protected $mFooter = '';
- protected $mSectionHeaders = array();
- protected $mSectionFooters = array();
+ protected $mSectionHeaders = [];
+ protected $mSectionFooters = [];
protected $mPost = '';
protected $mId;
+ protected $mName;
protected $mTableId = '';
protected $mSubmitID;
*/
protected $mAction = false;
+ /**
+ * Form attribute autocomplete. false does not set the attribute
+ * @since 1.27
+ * @var bool|string
+ */
+ protected $mAutocomplete = false;
+
protected $mUseMultipart = false;
- protected $mHiddenFields = array();
- protected $mButtons = array();
+ protected $mHiddenFields = [];
+ protected $mButtons = [];
protected $mWrapperLegend = false;
* Available formats in which to display the form
* @var array
*/
- protected $availableDisplayFormats = array(
+ protected $availableDisplayFormats = [
'table',
'div',
'raw',
'inline',
- );
+ ];
/**
* Available formats in which to display the form
* @var array
*/
- protected $availableSubclassDisplayFormats = array(
+ protected $availableSubclassDisplayFormats = [
'vform',
'ooui',
- );
+ ];
/**
* Construct a HTMLForm object for given display type. May return a HTMLForm subclass.
$this->setContext( $context );
$this->mTitle = false; // We don't need them to set a title
$this->mMessagePrefix = $messagePrefix;
- } elseif ( is_null( $context ) && $messagePrefix !== '' ) {
+ } elseif ( $context === null && $messagePrefix !== '' ) {
$this->mMessagePrefix = $messagePrefix;
} elseif ( is_string( $context ) && $messagePrefix === '' ) {
// B/C since 1.18
}
// Expand out into a tree.
- $loadedDescriptor = array();
- $this->mFlatFields = array();
+ $loadedDescriptor = [];
+ $this->mFlatFields = [];
foreach ( $descriptor as $fieldname => $info ) {
$section = isset( $info['section'] )
? $info['section']
: '';
- if ( isset( $info['type'] ) && $info['type'] == 'file' ) {
+ if ( isset( $info['type'] ) && $info['type'] === 'file' ) {
$this->mUseMultipart = true;
}
$newName = array_shift( $sectionParts );
if ( !isset( $setSection[$newName] ) ) {
- $setSection[$newName] = array();
+ $setSection[$newName] = [];
}
$setSection =& $setSection[$newName];
*/
public function setDisplayFormat( $format ) {
if (
- in_array( $format, $this->availableSubclassDisplayFormats ) ||
- in_array( $this->displayFormat, $this->availableSubclassDisplayFormats )
+ in_array( $format, $this->availableSubclassDisplayFormats, true ) ||
+ in_array( $this->displayFormat, $this->availableSubclassDisplayFormats, true )
) {
throw new MWException( 'Cannot change display format after creation, ' .
'use HTMLForm::factory() instead' );
}
- if ( !in_array( $format, $this->availableDisplayFormats ) ) {
+ if ( !in_array( $format, $this->availableDisplayFormats, true ) ) {
throw new MWException( 'Display format must be one of ' .
print_r( $this->availableDisplayFormats, true ) );
}
# @todo This will throw a fatal error whenever someone try to use
# 'class' to feed a CSS class instead of 'cssclass'. Would be
# great to avoid the fatal error and show a nice error.
- $obj = new $class( $descriptor );
-
- return $obj;
+ return new $class( $descriptor );
}
/**
* @throws MWException
* @return HTMLForm $this for chaining calls (since 1.20)
*/
- function prepareForm() {
+ public function prepareForm() {
# Check if we have the info we need
if ( !$this->mTitle instanceof Title && $this->mTitle !== false ) {
- throw new MWException( "You must call setTitle() on an HTMLForm" );
+ throw new MWException( 'You must call setTitle() on an HTMLForm' );
}
# Load data from the request.
* Try submitting, with edit token check first
* @return Status|bool
*/
- function tryAuthorizedSubmit() {
+ public function tryAuthorizedSubmit() {
$result = false;
$submit = false;
- if ( $this->getMethod() != 'post' ) {
+ if ( $this->getMethod() !== 'post' ) {
$submit = true; // no session check needed
} elseif ( $this->getRequest()->wasPosted() ) {
$editToken = $this->getRequest()->getVal( 'wpEditToken' );
- if ( $this->getUser()->isLoggedIn() || $editToken != null ) {
+ if ( $this->getUser()->isLoggedIn() || $editToken !== null ) {
// Session tokens for logged-out users have no security value.
// However, if the user gave one, check it in order to give a nice
// "session expired" error instead of "permission denied" or such.
* errors
* @return bool|Status Whether submission was successful.
*/
- function show() {
+ public function show() {
$this->prepareForm();
$result = $this->tryAuthorizedSubmit();
* added to the output, no matter, if the validation was good or not.
* @return bool|Status Whether submission was successful.
*/
- function showAlways() {
+ public function showAlways() {
$this->prepareForm();
$result = $this->tryAuthorizedSubmit();
* object, an HTML string, or an array of arrays (message keys and
* params) or strings (message keys)
*/
- function trySubmit() {
+ public function trySubmit() {
$valid = true;
- $hoistedErrors = array();
+ $hoistedErrors = [];
$hoistedErrors[] = isset( $this->mValidationErrorMessage )
? $this->mValidationErrorMessage
- : array( 'htmlform-invalid-input' );
+ : [ 'htmlform-invalid-input' ];
$this->mWasSubmitted = true;
if ( $res !== true ) {
$valid = false;
if ( $res !== false && !$field->canDisplayErrors() ) {
- $hoistedErrors[] = array( 'rawmessage', $res );
+ $hoistedErrors[] = [ 'rawmessage', $res ];
}
}
}
* @since 1.23
* @return bool
*/
- function wasSubmitted() {
+ public function wasSubmitted() {
return $this->mWasSubmitted;
}
*
* @return HTMLForm $this for chaining calls (since 1.20)
*/
- function setSubmitCallback( $cb ) {
+ public function setSubmitCallback( $cb ) {
$this->mSubmitCallback = $cb;
return $this;
*
* @return HTMLForm $this for chaining calls (since 1.20)
*/
- function setValidationErrorMessage( $msg ) {
+ public function setValidationErrorMessage( $msg ) {
$this->mValidationErrorMessage = $msg;
return $this;
*
* @return HTMLForm $this for chaining calls (since 1.20)
*/
- function setIntro( $msg ) {
+ public function setIntro( $msg ) {
$this->setPreText( $msg );
return $this;
*
* @return HTMLForm $this for chaining calls (since 1.20)
*/
- function setPreText( $msg ) {
+ public function setPreText( $msg ) {
$this->mPre = $msg;
return $this;
*
* @return HTMLForm $this for chaining calls (since 1.20)
*/
- function addPreText( $msg ) {
+ public function addPreText( $msg ) {
$this->mPre .= $msg;
return $this;
*
* @return HTMLForm $this for chaining calls (since 1.20)
*/
- function addHeaderText( $msg, $section = null ) {
- if ( is_null( $section ) ) {
+ public function addHeaderText( $msg, $section = null ) {
+ if ( $section === null ) {
$this->mHeader .= $msg;
} else {
if ( !isset( $this->mSectionHeaders[$section] ) ) {
*
* @return HTMLForm $this for chaining calls (since 1.20)
*/
- function setHeaderText( $msg, $section = null ) {
- if ( is_null( $section ) ) {
+ public function setHeaderText( $msg, $section = null ) {
+ if ( $section === null ) {
$this->mHeader = $msg;
} else {
$this->mSectionHeaders[$section] = $msg;
* @since 1.26
* @return string HTML
*/
- function getHeaderText( $section = null ) {
- if ( is_null( $section ) ) {
+ public function getHeaderText( $section = null ) {
+ if ( $section === null ) {
return $this->mHeader;
} else {
return isset( $this->mSectionHeaders[$section] ) ? $this->mSectionHeaders[$section] : '';
*
* @return HTMLForm $this for chaining calls (since 1.20)
*/
- function addFooterText( $msg, $section = null ) {
- if ( is_null( $section ) ) {
+ public function addFooterText( $msg, $section = null ) {
+ if ( $section === null ) {
$this->mFooter .= $msg;
} else {
if ( !isset( $this->mSectionFooters[$section] ) ) {
*
* @return HTMLForm $this for chaining calls (since 1.20)
*/
- function setFooterText( $msg, $section = null ) {
- if ( is_null( $section ) ) {
+ public function setFooterText( $msg, $section = null ) {
+ if ( $section === null ) {
$this->mFooter = $msg;
} else {
$this->mSectionFooters[$section] = $msg;
* @since 1.26
* @return string
*/
- function getFooterText( $section = null ) {
- if ( is_null( $section ) ) {
+ public function getFooterText( $section = null ) {
+ if ( $section === null ) {
return $this->mFooter;
} else {
return isset( $this->mSectionFooters[$section] ) ? $this->mSectionFooters[$section] : '';
*
* @return HTMLForm $this for chaining calls (since 1.20)
*/
- function addPostText( $msg ) {
+ public function addPostText( $msg ) {
$this->mPost .= $msg;
return $this;
*
* @return HTMLForm $this for chaining calls (since 1.20)
*/
- function setPostText( $msg ) {
+ public function setPostText( $msg ) {
$this->mPost = $msg;
return $this;
*
* @return HTMLForm $this for chaining calls (since 1.20)
*/
- public function addHiddenField( $name, $value, $attribs = array() ) {
- $attribs += array( 'name' => $name );
- $this->mHiddenFields[] = array( $value, $attribs );
+ public function addHiddenField( $name, $value, array $attribs = [] ) {
+ $attribs += [ 'name' => $name ];
+ $this->mHiddenFields[] = [ $value, $attribs ];
return $this;
}
*/
public function addHiddenFields( array $fields ) {
foreach ( $fields as $name => $value ) {
- $this->mHiddenFields[] = array( $value, array( 'name' => $name ) );
+ $this->mHiddenFields[] = [ $value, [ 'name' => $name ] ];
}
return $this;
'Incorrect number of arguments for deprecated calling style'
);
}
- $data = array(
+ $data = [
'name' => $args[0],
'value' => $args[1],
'id' => isset( $args[2] ) ? $args[2] : null,
'attribs' => isset( $args[3] ) ? $args[3] : null,
- );
+ ];
} else {
if ( !isset( $data['name'] ) ) {
throw new InvalidArgumentException( 'A name is required' );
throw new InvalidArgumentException( 'A value is required' );
}
}
- $this->mButtons[] = $data + array(
+ $this->mButtons[] = $data + [
'id' => null,
'attribs' => null,
'flags' => null,
- );
+ ];
return $this;
}
*
* @return void Nothing, should be last call
*/
- function displayForm( $submitResult ) {
+ public function displayForm( $submitResult ) {
$this->getOutput()->addHTML( $this->getHTML( $submitResult ) );
}
*
* @return string HTML
*/
- function getHTML( $submitResult ) {
+ public function getHTML( $submitResult ) {
# For good measure (it is the default)
$this->getOutput()->preventClickjacking();
$this->getOutput()->addModules( 'mediawiki.htmlform' );
? 'multipart/form-data'
: 'application/x-www-form-urlencoded';
# Attributes
- $attribs = array(
+ $attribs = [
'action' => $this->getAction(),
'method' => $this->getMethod(),
'enctype' => $encType,
- );
- if ( !empty( $this->mId ) ) {
+ ];
+ if ( $this->mId ) {
$attribs['id'] = $this->mId;
}
+ if ( $this->mAutocomplete ) {
+ $attribs['autocomplete'] = $this->mAutocomplete;
+ }
+ if ( $this->mName ) {
+ $attribs['name'] = $this->mName;
+ }
return $attribs;
}
*
* @return string Wrapped HTML.
*/
- function wrapForm( $html ) {
+ public function wrapForm( $html ) {
# Include a <fieldset> wrapper for style, if requested.
if ( $this->mWrapperLegend !== false ) {
$legend = is_string( $this->mWrapperLegend ) ? $this->mWrapperLegend : false;
return Html::rawElement(
'form',
- $this->getFormAttributes() + array( 'class' => 'visualClear' ),
+ $this->getFormAttributes() + [ 'class' => 'visualClear' ],
$html
);
}
* Get the hidden fields that should go inside the form.
* @return string HTML.
*/
- function getHiddenFields() {
+ public function getHiddenFields() {
$html = '';
- if ( $this->getMethod() == 'post' ) {
+ if ( $this->getMethod() === 'post' ) {
$html .= Html::hidden(
'wpEditToken',
$this->getUser()->getEditToken( $this->mTokenSalt ),
- array( 'id' => 'wpEditToken' )
+ [ 'id' => 'wpEditToken' ]
) . "\n";
$html .= Html::hidden( 'title', $this->getTitle()->getPrefixedText() ) . "\n";
}
$articlePath = $this->getConfig()->get( 'ArticlePath' );
- if ( strpos( $articlePath, '?' ) !== false && $this->getMethod() == 'get' ) {
+ if ( strpos( $articlePath, '?' ) !== false && $this->getMethod() === 'get' ) {
$html .= Html::hidden( 'title', $this->getTitle()->getPrefixedText() ) . "\n";
}
* Get the submit and (potentially) reset buttons.
* @return string HTML.
*/
- function getButtons() {
+ public function getButtons() {
$buttons = '';
$useMediaWikiUIEverywhere = $this->getConfig()->get( 'UseMediaWikiUIEverywhere' );
if ( $this->mShowSubmit ) {
- $attribs = array();
+ $attribs = [];
if ( isset( $this->mSubmitID ) ) {
$attribs['id'] = $this->mSubmitID;
$attribs += Linker::tooltipAndAccesskeyAttribs( $this->mSubmitTooltip );
}
- $attribs['class'] = array( 'mw-htmlform-submit' );
+ $attribs['class'] = [ 'mw-htmlform-submit' ];
if ( $useMediaWikiUIEverywhere ) {
foreach ( $this->mSubmitFlags as $flag ) {
- array_push( $attribs['class'], 'mw-ui-' . $flag );
+ $attribs['class'][] = 'mw-ui-' . $flag;
}
- array_push( $attribs['class'], 'mw-ui-button' );
+ $attribs['class'][] = 'mw-ui-button';
}
$buttons .= Xml::submitButton( $this->getSubmitText(), $attribs ) . "\n";
if ( $this->mShowReset ) {
$buttons .= Html::element(
'input',
- array(
+ [
'type' => 'reset',
'value' => $this->msg( 'htmlform-reset' )->text(),
- 'class' => ( $useMediaWikiUIEverywhere ? 'mw-ui-button' : null ),
- )
+ 'class' => $useMediaWikiUIEverywhere ? 'mw-ui-button' : null,
+ ]
) . "\n";
}
$isBadIE = preg_match( '/MSIE [1-7]\./i', $this->getRequest()->getHeader( 'User-Agent' ) );
foreach ( $this->mButtons as $button ) {
- $attrs = array(
+ $attrs = [
'type' => 'submit',
'name' => $button['name'],
'value' => $button['value']
- );
+ ];
if ( isset( $button['label-message'] ) ) {
$label = $this->msg( $button['label-message'] )->parse();
}
if ( $useMediaWikiUIEverywhere ) {
- $attrs['class'] = isset( $attrs['class'] ) ? (array)$attrs['class'] : array();
+ $attrs['class'] = isset( $attrs['class'] ) ? (array)$attrs['class'] : [];
$attrs['class'][] = 'mw-ui-button';
}
}
$html = Html::rawElement( 'span',
- array( 'class' => 'mw-htmlform-submit-buttons' ), "\n$buttons" ) . "\n";
+ [ 'class' => 'mw-htmlform-submit-buttons' ], "\n$buttons" ) . "\n";
return $html;
}
* Get the whole body of the form.
* @return string
*/
- function getBody() {
+ public function getBody() {
return $this->displaySection( $this->mFieldTree, $this->mTableId );
}
*
* @return string
*/
- function getErrors( $errors ) {
+ public function getErrors( $errors ) {
if ( $errors instanceof Status ) {
if ( $errors->isOK() ) {
$errorstr = '';
}
return $errorstr
- ? Html::rawElement( 'div', array( 'class' => 'error' ), $errorstr )
+ ? Html::rawElement( 'div', [ 'class' => 'error' ], $errorstr )
: '';
}
$msg = array_shift( $error );
} else {
$msg = $error;
- $error = array();
+ $error = [];
}
$errorstr .= Html::rawElement(
'li',
- array(),
+ [],
$this->msg( $msg, $error )->parse()
);
}
- $errorstr = Html::rawElement( 'ul', array(), $errorstr );
+ $errorstr = Html::rawElement( 'ul', [], $errorstr );
return $errorstr;
}
*
* @return HTMLForm $this for chaining calls (since 1.20)
*/
- function setSubmitText( $t ) {
+ public function setSubmitText( $t ) {
$this->mSubmitText = $t;
return $this;
* @since 1.24
*/
public function setSubmitDestructive() {
- $this->mSubmitFlags = array( 'destructive', 'primary' );
-
- return $this;
+ $this->mSubmitFlags = [ 'destructive', 'primary' ];
}
/**
* @since 1.25
*/
public function setSubmitProgressive() {
- $this->mSubmitFlags = array( 'progressive', 'primary' );
-
- return $this;
+ $this->mSubmitFlags = [ 'progressive', 'primary' ];
}
/**
* Get the text for the submit button, either customised or a default.
* @return string
*/
- function getSubmitText() {
- return $this->mSubmitText
- ? $this->mSubmitText
- : $this->msg( 'htmlform-submit' )->text();
+ public function getSubmitText() {
+ return $this->mSubmitText ?: $this->msg( 'htmlform-submit' )->text();
}
/**
* @todo FIXME: Integrity of $t is *not* validated
* @return HTMLForm $this for chaining calls (since 1.20)
*/
- function setSubmitID( $t ) {
+ public function setSubmitID( $t ) {
$this->mSubmitID = $t;
return $this;
*
* @return HTMLForm $this for chaining calls
*/
- function suppressDefaultSubmit( $suppressSubmit = true ) {
+ public function suppressDefaultSubmit( $suppressSubmit = true ) {
$this->mShowSubmit = !$suppressSubmit;
return $this;
return $this;
}
+ /**
+ * @param string $name 'name' attribute for the form
+ * @return HTMLForm $this for chaining calls
+ */
+ public function setName( $name ) {
+ $this->mName = $name;
+
+ return $this;
+ }
+
/**
* Prompt the whole form to be wrapped in a "<fieldset>", with
* this text as its "<legend>" element.
*
* @return HTMLForm $this for chaining calls (since 1.20)
*/
- function setMessagePrefix( $p ) {
+ public function setMessagePrefix( $p ) {
$this->mMessagePrefix = $p;
return $this;
*
* @return HTMLForm $this for chaining calls (since 1.20)
*/
- function setTitle( $t ) {
+ public function setTitle( $t ) {
$this->mTitle = $t;
return $this;
* Get the title
* @return Title
*/
- function getTitle() {
+ public function getTitle() {
return $this->mTitle === false
? $this->getContext()->getTitle()
: $this->mTitle;
&$hasUserVisibleFields = false ) {
$displayFormat = $this->getDisplayFormat();
- $html = array();
+ $html = [];
$subsectionHtml = '';
$hasLabel = false;
// Conveniently, PHP method names are case-insensitive.
// For grep: this can call getDiv, getRaw, getInline, getVForm, getOOUI
- $getFieldHtmlMethod = $displayFormat == 'table' ? 'getTableRow' : ( 'get' . $displayFormat );
+ $getFieldHtmlMethod = $displayFormat === 'table' ? 'getTableRow' : ( 'get' . $displayFormat );
foreach ( $fields as $key => $value ) {
if ( $value instanceof HTMLFormField ) {
$html[] = $retval;
$labelValue = trim( $value->getLabel() );
- if ( $labelValue != ' ' && $labelValue !== '' ) {
+ if ( $labelValue !== ' ' && $labelValue !== '' ) {
$hasLabel = true;
}
$section .
$this->getFooterText( $key );
- $attributes = array();
+ $attributes = [];
if ( $fieldsetIDPrefix ) {
$attributes['id'] = Sanitizer::escapeId( "$fieldsetIDPrefix$key" );
}
return $html;
}
- $classes = array();
+ $classes = [];
if ( !$anyFieldHasLabel ) { // Avoid strange spacing when no labels exist
$classes[] = 'mw-htmlform-nolabel';
}
- $attribs = array(
+ $attribs = [
'class' => implode( ' ', $classes ),
- );
+ ];
if ( $sectionName ) {
$attribs['id'] = Sanitizer::escapeId( $sectionName );
if ( $displayFormat === 'table' ) {
return Html::rawElement( 'table',
$attribs,
- Html::rawElement( 'tbody', array(), "\n$html\n" ) ) . "\n";
+ Html::rawElement( 'tbody', [], "\n$html\n" ) ) . "\n";
} elseif ( $displayFormat === 'inline' ) {
return Html::rawElement( 'span', $attribs, "\n$html\n" );
} else {
/**
* Construct the form fields from the Descriptor array
*/
- function loadData() {
- $fieldData = array();
+ public function loadData() {
+ $fieldData = [];
foreach ( $this->mFlatFields as $fieldname => $field ) {
if ( !empty( $field->mParams['nodata'] ) ) {
*
* @return HTMLForm $this for chaining calls (since 1.20)
*/
- function suppressReset( $suppressReset = true ) {
+ public function suppressReset( $suppressReset = true ) {
$this->mShowReset = !$suppressReset;
return $this;
*
* @return array
*/
- function filterDataForSubmit( $data ) {
+ public function filterDataForSubmit( $data ) {
return $data;
}
return $this->getTitle()->getLocalURL();
}
+
+ /**
+ * Set the value for the autocomplete attribute of the form.
+ * When set to false (which is the default state), the attribute get not set.
+ *
+ * @since 1.27
+ *
+ * @param string|bool $autocomplete
+ *
+ * @return HTMLForm $this for chaining calls
+ */
+ public function setAutocomplete( $autocomplete ) {
+ $this->mAutocomplete = $autocomplete;
+
+ return $this;
+ }
}