element.
*
* @since 1.22
*
* @param string $id New value of the id attribute, or "" to remove
*
* @return HTMLForm $this for chaining calls
*/
public function setTableId( $id ) {
$this->mTableId = $id;
return $this;
}
/**
* @param string $id DOM id for the form
*
* @return HTMLForm $this for chaining calls (since 1.20)
*/
public function setId( $id ) {
$this->mId = $id;
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 "
", with
* this text as its "" element.
*
* @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)
*/
public function setWrapperLegend( $legend ) {
$this->mWrapperLegend = $legend;
return $this;
}
/**
* For internal use only. Use is discouraged, and should only be used where
* support for gadgets/user scripts is warranted.
* @param array $attributes
* @internal
* @return HTMLForm $this for chaining calls
*/
public function setWrapperAttributes( $attributes ) {
$this->mWrapperAttributes = $attributes;
return $this;
}
/**
* Prompt the whole form to be wrapped in a " ", with
* this message as its "" element.
* @since 1.19
*
* @param string|Message $msg Message key or Message object
*
* @return HTMLForm $this for chaining calls (since 1.20)
*/
public function setWrapperLegendMsg( $msg ) {
if ( !$msg instanceof Message ) {
$msg = $this->msg( $msg );
}
$this->setWrapperLegend( $msg->text() );
return $this;
}
/**
* Set the prefix for various default messages
* @todo Currently only used for the " " legend on forms
* with multiple sections; should be used elsewhere?
*
* @param string $p
*
* @return HTMLForm $this for chaining calls (since 1.20)
*/
public function setMessagePrefix( $p ) {
$this->mMessagePrefix = $p;
return $this;
}
/**
* Set the title for form submission
*
* @param Title $t Title of page the form is on/should be posted to
*
* @return HTMLForm $this for chaining calls (since 1.20)
*/
public function setTitle( $t ) {
$this->mTitle = $t;
return $this;
}
/**
* Get the title
* @return Title
*/
public function getTitle() {
return $this->mTitle === false
? $this->getContext()->getTitle()
: $this->mTitle;
}
/**
* Set the method used to submit the form
*
* @param string $method
*
* @return HTMLForm $this for chaining calls (since 1.20)
*/
public function setMethod( $method = 'post' ) {
$this->mMethod = strtolower( $method );
return $this;
}
/**
* @return string Always lowercase
*/
public function getMethod() {
return $this->mMethod;
}
/**
* Wraps the given $section into an user-visible fieldset.
* @stable to override
*
* @param string $legend Legend text for the fieldset
* @param string $section The section content in plain Html
* @param array $attributes Additional attributes for the fieldset
* @param bool $isRoot Section is at the root of the tree
* @return string The fieldset's Html
*/
protected function wrapFieldSetSection( $legend, $section, $attributes, $isRoot ) {
return Xml::fieldset( $legend, $section, $attributes ) . "\n";
}
/**
* @todo Document
* @stable to override
*
* @param array[]|HTMLFormField[] $fields Array of fields (either arrays or
* objects).
* @param string $sectionName ID attribute of the "" tag for this
* section, ignored if empty.
* @param string $fieldsetIDPrefix ID prefix for the "" tag of
* each subsection, ignored if empty.
* @param bool &$hasUserVisibleFields Whether the section had user-visible fields.
* @throws LogicException When called on uninitialized field data, e.g. When
* HTMLForm::displayForm was called without calling HTMLForm::prepareForm
* first.
*
* @return string
*/
public function displaySection( $fields,
$sectionName = '',
$fieldsetIDPrefix = '',
&$hasUserVisibleFields = false
) {
if ( $this->mFieldData === null ) {
throw new LogicException( 'HTMLForm::displaySection() called on uninitialized field data. '
. 'You probably called displayForm() without calling prepareForm() first.' );
}
$displayFormat = $this->getDisplayFormat();
$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 );
foreach ( $fields as $key => $value ) {
if ( $value instanceof HTMLFormField ) {
$v = array_key_exists( $key, $this->mFieldData )
? $this->mFieldData[$key]
: $value->getDefault();
$retval = $value->$getFieldHtmlMethod( $v );
// check, if the form field should be added to
// the output.
if ( $value->hasVisibleOutput() ) {
$html[] = $retval;
$labelValue = trim( $value->getLabel() );
if ( $labelValue !== "\u{00A0}" && $labelValue !== ' ' && $labelValue !== '' ) {
$hasLabel = true;
}
$hasUserVisibleFields = true;
}
} elseif ( is_array( $value ) ) {
$subsectionHasVisibleFields = false;
$section =
$this->displaySection( $value,
"mw-htmlform-$key",
"$fieldsetIDPrefix$key-",
$subsectionHasVisibleFields );
$legend = null;
if ( $subsectionHasVisibleFields === true ) {
// Display the section with various niceties.
$hasUserVisibleFields = true;
$legend = $this->getLegend( $key );
$section = $this->getHeaderText( $key ) .
$section .
$this->getFooterText( $key );
$attributes = [];
if ( $fieldsetIDPrefix ) {
$attributes['id'] = Sanitizer::escapeIdForAttribute( "$fieldsetIDPrefix$key" );
}
$subsectionHtml .= $this->wrapFieldSetSection(
$legend, $section, $attributes, $fields === $this->mFieldTree
);
} else {
// Just return the inputs, nothing fancy.
$subsectionHtml .= $section;
}
}
}
$html = $this->formatSection( $html, $sectionName, $hasLabel );
if ( $subsectionHtml ) {
if ( $this->mSubSectionBeforeFields ) {
return $subsectionHtml . "\n" . $html;
} else {
return $html . "\n" . $subsectionHtml;
}
} else {
return $html;
}
}
/**
* Put a form section together from the individual fields' HTML, merging it and wrapping.
* @stable to override
* @param array $fieldsHtml
* @param string $sectionName
* @param bool $anyFieldHasLabel
* @return string HTML
*/
protected function formatSection( array $fieldsHtml, $sectionName, $anyFieldHasLabel ) {
if ( !$fieldsHtml ) {
// Do not generate any wrappers for empty sections. Sections may be empty if they only have
// subsections, but no fields. A legend will still be added in wrapFieldSetSection().
return '';
}
$displayFormat = $this->getDisplayFormat();
$html = implode( '', $fieldsHtml );
if ( $displayFormat === 'raw' ) {
return $html;
}
$classes = [];
if ( !$anyFieldHasLabel ) { // Avoid strange spacing when no labels exist
$classes[] = 'mw-htmlform-nolabel';
}
$attribs = [
'class' => implode( ' ', $classes ),
];
if ( $sectionName ) {
$attribs['id'] = Sanitizer::escapeIdForAttribute( $sectionName );
}
if ( $displayFormat === 'table' ) {
return Html::rawElement( 'table',
$attribs,
Html::rawElement( 'tbody', [], "\n$html\n" ) ) . "\n";
} elseif ( $displayFormat === 'inline' ) {
return Html::rawElement( 'span', $attribs, "\n$html\n" );
} else {
return Html::rawElement( 'div', $attribs, "\n$html\n" );
}
}
/**
* Construct the form fields from the Descriptor array
*/
public function loadData() {
$fieldData = [];
foreach ( $this->mFlatFields as $fieldname => $field ) {
$request = $this->getRequest();
if ( $field->skipLoadData( $request ) ) {
continue;
} elseif ( !empty( $field->mParams['disabled'] ) ) {
$fieldData[$fieldname] = $field->getDefault();
} else {
$fieldData[$fieldname] = $field->loadDataFromRequest( $request );
}
}
# Filter data.
foreach ( $fieldData as $name => &$value ) {
$field = $this->mFlatFields[$name];
$value = $field->filter( $value, $this->mFlatFields );
}
$this->mFieldData = $fieldData;
}
/**
* Stop a reset button being shown for this form
*
* @param bool $suppressReset Set to false to re-enable the button again
*
* @return HTMLForm $this for chaining calls (since 1.20)
*/
public function suppressReset( $suppressReset = true ) {
$this->mShowReset = !$suppressReset;
return $this;
}
/**
* Overload this if you want to apply special filtration routines
* to the form as a whole, after it's submitted but before it's
* processed.
* @stable to override
*
* @param array $data
*
* @return array
*/
public function filterDataForSubmit( $data ) {
return $data;
}
/**
* Get a string to go in the "" of a section fieldset.
* Override this if you want something more complicated.
* @stable to override
*
* @param string $key
*
* @return string Plain text (not HTML-escaped)
*/
public function getLegend( $key ) {
return $this->msg( $this->mMessagePrefix ? "{$this->mMessagePrefix}-$key" : $key )->text();
}
/**
* Set the value for the action attribute of the form.
* When set to false (which is the default state), the set title is used.
*
* @since 1.19
*
* @param string|bool $action
*
* @return HTMLForm $this for chaining calls (since 1.20)
*/
public function setAction( $action ) {
$this->mAction = $action;
return $this;
}
/**
* Get the value for the action attribute of the form.
*
* @since 1.22
*
* @return string
*/
public function getAction() {
// If an action is alredy provided, return it
if ( $this->mAction !== false ) {
return $this->mAction;
}
$articlePath = $this->getConfig()->get( 'ArticlePath' );
// Check whether we are in GET mode and the ArticlePath contains a "?"
// meaning that getLocalURL() would return something like "index.php?title=...".
// As browser remove the query string before submitting GET forms,
// it means that the title would be lost. In such case use wfScript() instead
// and put title in an hidden field (see getHiddenFields()).
if ( strpos( $articlePath, '?' ) !== false && $this->getMethod() === 'get' ) {
return wfScript();
}
return $this->getTitle()->getLocalURL();
}
/**
* Set the value for the autocomplete attribute of the form. A typical value is "off".
* When set to null (which is the default state), the attribute get not set.
*
* @since 1.27
*
* @param string|null $autocomplete
*
* @return HTMLForm $this for chaining calls
*/
public function setAutocomplete( $autocomplete ) {
$this->mAutocomplete = $autocomplete;
return $this;
}
/**
* Turns a *-message parameter (which could be a MessageSpecifier, or a message name, or a
* name + parameters array) into a Message.
* @param mixed $value
* @return Message
*/
protected function getMessage( $value ) {
return Message::newFromSpecifier( $value )->setContext( $this );
}
/**
* Whether this form, with its current fields, requires the user agent to have JavaScript enabled
* for the client-side HTML5 form validation to work correctly. If this function returns true, a
* 'novalidate' attribute will be added on the `