user: Allow "CAS update failed" exceptions to be normalised
[lhc/web/wiklou.git] / includes / htmlform / fields / HTMLTextField.php
1 <?php
2
3 /**
4 * <input> field.
5 *
6 * Besides the parameters recognized by HTMLFormField, the following are
7 * recognized:
8 * autocomplete - HTML autocomplete value (a boolean for on/off or a string according to
9 * https://html.spec.whatwg.org/multipage/forms.html#autofill )
10 */
11 class HTMLTextField extends HTMLFormField {
12 protected $mPlaceholder = '';
13
14 /** @var bool HTML autocomplete attribute */
15 protected $autocomplete;
16
17 /**
18 * @param array $params
19 * - type: HTML textfield type
20 * - size: field size in characters (defaults to 45)
21 * - placeholder/placeholder-message: set HTML placeholder attribute
22 * - spellcheck: set HTML spellcheck attribute
23 * - persistent: upon unsuccessful requests, retain the value (defaults to true, except
24 * for password fields)
25 */
26 public function __construct( $params ) {
27 if ( isset( $params['autocomplete'] ) && is_bool( $params['autocomplete'] ) ) {
28 $params['autocomplete'] = $params['autocomplete'] ? 'on' : 'off';
29 }
30
31 parent::__construct( $params );
32
33 if ( isset( $params['placeholder-message'] ) ) {
34 $this->mPlaceholder = $this->getMessage( $params['placeholder-message'] )->text();
35 } elseif ( isset( $params['placeholder'] ) ) {
36 $this->mPlaceholder = $params['placeholder'];
37 }
38 }
39
40 public function getSize() {
41 return $this->mParams['size'] ?? 45;
42 }
43
44 public function getSpellCheck() {
45 $val = $this->mParams['spellcheck'] ?? null;
46 if ( is_bool( $val ) ) {
47 // "spellcheck" attribute literally requires "true" or "false" to work.
48 return $val === true ? 'true' : 'false';
49 }
50 return null;
51 }
52
53 public function isPersistent() {
54 if ( isset( $this->mParams['persistent'] ) ) {
55 return $this->mParams['persistent'];
56 }
57 // don't put passwords into the HTML body, they could get cached or otherwise leaked
58 return !( isset( $this->mParams['type'] ) && $this->mParams['type'] === 'password' );
59 }
60
61 public function getInputHTML( $value ) {
62 if ( !$this->isPersistent() ) {
63 $value = '';
64 }
65
66 $attribs = [
67 'id' => $this->mID,
68 'name' => $this->mName,
69 'size' => $this->getSize(),
70 'value' => $value,
71 'dir' => $this->mDir,
72 'spellcheck' => $this->getSpellCheck(),
73 ] + $this->getTooltipAndAccessKey() + $this->getDataAttribs();
74
75 if ( $this->mClass !== '' ) {
76 $attribs['class'] = $this->mClass;
77 }
78 if ( $this->mPlaceholder !== '' ) {
79 $attribs['placeholder'] = $this->mPlaceholder;
80 }
81
82 # @todo Enforce pattern, step, required, readonly on the server side as
83 # well
84 $allowedParams = [
85 'type',
86 'min',
87 'max',
88 'pattern',
89 'title',
90 'step',
91 'list',
92 'maxlength',
93 'tabindex',
94 'disabled',
95 'required',
96 'autofocus',
97 'multiple',
98 'readonly',
99 'autocomplete',
100 ];
101
102 $attribs += $this->getAttributes( $allowedParams );
103
104 # Extract 'type'
105 $type = $this->getType( $attribs );
106 return Html::input( $this->mName, $value, $type, $attribs );
107 }
108
109 protected function getType( &$attribs ) {
110 $type = $attribs['type'] ?? 'text';
111 unset( $attribs['type'] );
112
113 # Implement tiny differences between some field variants
114 # here, rather than creating a new class for each one which
115 # is essentially just a clone of this one.
116 if ( isset( $this->mParams['type'] ) ) {
117 switch ( $this->mParams['type'] ) {
118 case 'int':
119 $type = 'number';
120 $attribs['step'] = 1;
121 break;
122 case 'float':
123 $type = 'number';
124 $attribs['step'] = 'any';
125 break;
126 # Pass through
127 case 'email':
128 case 'password':
129 case 'file':
130 case 'url':
131 $type = $this->mParams['type'];
132 break;
133 }
134 }
135
136 return $type;
137 }
138
139 public function getInputOOUI( $value ) {
140 if ( !$this->isPersistent() ) {
141 $value = '';
142 }
143
144 $attribs = $this->getTooltipAndAccessKeyOOUI();
145
146 if ( $this->mClass !== '' ) {
147 $attribs['classes'] = [ $this->mClass ];
148 }
149 if ( $this->mPlaceholder !== '' ) {
150 $attribs['placeholder'] = $this->mPlaceholder;
151 }
152
153 # @todo Enforce pattern, step, required, readonly on the server side as
154 # well
155 $allowedParams = [
156 'autofocus',
157 'autosize',
158 'disabled',
159 'flags',
160 'indicator',
161 'maxlength',
162 'readonly',
163 'required',
164 'tabindex',
165 'type',
166 'autocomplete',
167 ];
168
169 $attribs += OOUI\Element::configFromHtmlAttributes(
170 $this->getAttributes( $allowedParams )
171 );
172
173 // FIXME T150983 downgrade autocomplete
174 if ( isset( $attribs['autocomplete'] ) ) {
175 if ( $attribs['autocomplete'] === 'on' ) {
176 $attribs['autocomplete'] = true;
177 } elseif ( $attribs['autocomplete'] === 'off' ) {
178 $attribs['autocomplete'] = false;
179 } else {
180 unset( $attribs['autocomplete'] );
181 }
182 }
183
184 $type = $this->getType( $attribs );
185 if ( isset( $attribs['step'] ) && $attribs['step'] === 'any' ) {
186 $attribs['step'] = null;
187 }
188
189 return $this->getInputWidget( [
190 'id' => $this->mID,
191 'name' => $this->mName,
192 'value' => $value,
193 'type' => $type,
194 'dir' => $this->mDir,
195 ] + $attribs );
196 }
197
198 protected function getInputWidget( $params ) {
199 return new OOUI\TextInputWidget( $params );
200 }
201
202 /**
203 * Returns an array of data-* attributes to add to the field.
204 *
205 * @return array
206 */
207 protected function getDataAttribs() {
208 return [];
209 }
210 }