From 8f17b09a9fd04ed673a1e0c184d0ecf1926270a6 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Gerg=C5=91=20Tisza?= Date: Thu, 17 Nov 2016 18:39:23 +0000 Subject: [PATCH] Add 'autocomplete' option to HTMLTextField Adds support for the 'autocomplete' HTML attribute to HTMLTextField (mainly for turning it off, but other values are supported as well). Renames 'autocomplete' to 'autocomplete-data' (with temporary B/C) in HTMLAutoCompleteSelectField to make space. Change-Id: Ic0539d5a61d9862e670d10686adc1e41f65d908e --- .../fields/HTMLAutoCompleteSelectField.php | 52 +++++++++++++------ includes/htmlform/fields/HTMLTextField.php | 30 ++++++++++- .../HTMLAutoCompleteSelectFieldTest.php | 6 +-- 3 files changed, 68 insertions(+), 20 deletions(-) diff --git a/includes/htmlform/fields/HTMLAutoCompleteSelectField.php b/includes/htmlform/fields/HTMLAutoCompleteSelectField.php index 76a88d5121..ebe57702d6 100644 --- a/includes/htmlform/fields/HTMLAutoCompleteSelectField.php +++ b/includes/htmlform/fields/HTMLAutoCompleteSelectField.php @@ -18,35 +18,55 @@ * options-messages - As for HTMLSelectField * options - As for HTMLSelectField * options-message - As for HTMLSelectField - * autocomplete - Associative array mapping display text to values. - * autocomplete-messages - Like autocomplete, but keys are message names. + * autocomplete-data - Associative array mapping display text to values. + * autocomplete-data-messages - Like autocomplete, but keys are message names. * require-match - Boolean, if true the value must be in the options or the * autocomplete. * other-message - Message to use instead of htmlform-selectorother-other for * the 'other' message. * other - Raw text to use for the 'other' message + * + * The old name of autocomplete-data[-messages] was autocomplete[-messages] which is still + * recognized but deprecated since MediaWiki 1.29 since it conflicts with how autocomplete is + * used in HTMLTextField. */ class HTMLAutoCompleteSelectField extends HTMLTextField { - protected $autocomplete = []; + protected $autocompleteData = []; function __construct( $params ) { $params += [ 'require-match' => false, ]; + // FIXME B/C, remove in 1.30 + if ( + array_key_exists( 'autocomplete', $params ) + && !array_key_exists( 'autocomplete-data', $params ) + ) { + $params['autocomplete-data'] = $params['autocomplete']; + unset( $params['autocomplete'] ); + } + if ( + array_key_exists( 'autocomplete-messages', $params ) + && !array_key_exists( 'autocomplete-data-messages', $params ) + ) { + $params['autocomplete-data-messages'] = $params['autocomplete-messages']; + unset( $params['autocomplete-messages'] ); + } + parent::__construct( $params ); - if ( array_key_exists( 'autocomplete-messages', $this->mParams ) ) { - foreach ( $this->mParams['autocomplete-messages'] as $key => $value ) { + if ( array_key_exists( 'autocomplete-data-messages', $this->mParams ) ) { + foreach ( $this->mParams['autocomplete-data-messages'] as $key => $value ) { $key = $this->msg( $key )->plain(); - $this->autocomplete[$key] = strval( $value ); + $this->autocompleteData[$key] = strval( $value ); } - } elseif ( array_key_exists( 'autocomplete', $this->mParams ) ) { - foreach ( $this->mParams['autocomplete'] as $key => $value ) { - $this->autocomplete[$key] = strval( $value ); + } elseif ( array_key_exists( 'autocomplete-data', $this->mParams ) ) { + foreach ( $this->mParams['autocomplete-data'] as $key => $value ) { + $this->autocompleteData[$key] = strval( $value ); } } - if ( !is_array( $this->autocomplete ) || !$this->autocomplete ) { + if ( !is_array( $this->autocompleteData ) || !$this->autocompleteData ) { throw new MWException( 'HTMLAutoCompleteSelectField called without any autocompletions' ); } @@ -69,8 +89,8 @@ class HTMLAutoCompleteSelectField extends HTMLTextField { if ( $val === 'other' ) { $val = $request->getText( $this->mName ); - if ( isset( $this->autocomplete[$val] ) ) { - $val = $this->autocomplete[$val]; + if ( isset( $this->autocompleteData[$val] ) ) { + $val = $this->autocompleteData[$val]; } } @@ -87,11 +107,11 @@ class HTMLAutoCompleteSelectField extends HTMLTextField { return $p; } - $validOptions = HTMLFormField::flattenOptions( $this->getOptions() ); + $validOptions = HTMLFormField::flattenOptions( $this->getOptions() ?: [] ); if ( in_array( strval( $value ), $validOptions, true ) ) { return true; - } elseif ( in_array( strval( $value ), $this->autocomplete, true ) ) { + } elseif ( in_array( strval( $value ), $this->autocompleteData, true ) ) { return true; } elseif ( $this->mParams['require-match'] ) { return $this->msg( 'htmlform-select-badoption' )->parse(); @@ -104,7 +124,7 @@ class HTMLAutoCompleteSelectField extends HTMLTextField { public function getAttributes( array $list ) { $attribs = [ 'type' => 'text', - 'data-autocomplete' => FormatJson::encode( array_keys( $this->autocomplete ) ), + 'data-autocomplete' => FormatJson::encode( array_keys( $this->autocompleteData ) ), ] + parent::getAttributes( $list ); if ( $this->getOptions() ) { @@ -152,7 +172,7 @@ class HTMLAutoCompleteSelectField extends HTMLTextField { if ( $valInSelect ) { $value = ''; } else { - $key = array_search( strval( $value ), $this->autocomplete, true ); + $key = array_search( strval( $value ), $this->autocompleteData, true ); if ( $key !== false ) { $value = $key; } diff --git a/includes/htmlform/fields/HTMLTextField.php b/includes/htmlform/fields/HTMLTextField.php index 3ab7176696..c1955975ce 100644 --- a/includes/htmlform/fields/HTMLTextField.php +++ b/includes/htmlform/fields/HTMLTextField.php @@ -1,8 +1,19 @@ field. + * + * Besides the parameters recognized by HTMLFormField, the following are + * recognized: + * autocomplete - HTML autocomplete value (a boolean for on/off or a string according to + * https://html.spec.whatwg.org/multipage/forms.html#autofill ) + */ class HTMLTextField extends HTMLFormField { protected $mPlaceholder = ''; + /** @var bool HTML autocomplete attribute */ + protected $autocomplete; + /** * @param array $params * - type: HTML textfield type @@ -13,6 +24,10 @@ class HTMLTextField extends HTMLFormField { * for password fields) */ public function __construct( $params ) { + if ( isset( $params['autocomplete'] ) && is_bool( $params['autocomplete'] ) ) { + $params['autocomplete'] = $params['autocomplete'] ? 'on' : 'off'; + } + parent::__construct( $params ); if ( isset( $params['placeholder-message'] ) ) { @@ -80,7 +95,8 @@ class HTMLTextField extends HTMLFormField { 'required', 'autofocus', 'multiple', - 'readonly' + 'readonly', + 'autocomplete', ]; $attribs += $this->getAttributes( $allowedParams ); @@ -146,12 +162,24 @@ class HTMLTextField extends HTMLFormField { 'required', 'tabindex', 'type', + 'autocomplete', ]; $attribs += OOUI\Element::configFromHtmlAttributes( $this->getAttributes( $allowedParams ) ); + // FIXME T150983 downgrade autocomplete + if ( isset( $attribs['autocomplete'] ) ) { + if ( $attribs['autocomplete'] === 'on' ) { + $attribs['autocomplete'] = true; + } elseif ( $attribs['autocomplete'] === 'off' ) { + $attribs['autocomplete'] = false; + } else { + unset( $attribs['autocomplete'] ); + } + } + $type = $this->getType( $attribs ); return $this->getInputWidget( [ diff --git a/tests/phpunit/includes/htmlform/HTMLAutoCompleteSelectFieldTest.php b/tests/phpunit/includes/htmlform/HTMLAutoCompleteSelectFieldTest.php index fbabf7ffad..33e3a257d2 100644 --- a/tests/phpunit/includes/htmlform/HTMLAutoCompleteSelectFieldTest.php +++ b/tests/phpunit/includes/htmlform/HTMLAutoCompleteSelectFieldTest.php @@ -49,9 +49,9 @@ class HtmlAutoCompleteSelectFieldTest extends MediaWikiTestCase { */ function testOptionalSelectElement() { $params = [ - 'fieldname' => 'Test', - 'autocomplete' => $this->options, - 'options' => $this->options, + 'fieldname' => 'Test', + 'autocomplete-data' => $this->options, + 'options' => $this->options, ]; $field = new HTMLAutoCompleteSelectField( $params ); -- 2.20.1