Localisation updates from https://translatewiki.net.
[mediawiki.git] / includes / htmlform / fields / HTMLTextField.php
blob6d187f0650f2ffbdbca994e1e61cbcb35f52b628
1 <?php
3 namespace MediaWiki\HTMLForm\Field;
5 use MediaWiki\Html\Html;
6 use MediaWiki\HTMLForm\HTMLFormField;
7 use OOUI\Widget;
9 /**
10 * <input> field.
12 * Besides the parameters recognized by HTMLFormField, the following are
13 * recognized:
14 * autocomplete - HTML autocomplete value (a boolean for on/off or a string according to
15 * https://html.spec.whatwg.org/multipage/forms.html#autofill )
17 * @stable to extend
19 class HTMLTextField extends HTMLFormField {
20 /** @var string */
21 protected $mPlaceholder = '';
23 /** @var bool HTML autocomplete attribute */
24 protected $autocomplete;
26 /**
27 * @stable to call
29 * @param array $params
30 * - type: HTML textfield type
31 * - size: field size in characters (defaults to 45)
32 * - placeholder/placeholder-message: set HTML placeholder attribute
33 * - spellcheck: set HTML spellcheck attribute
34 * - persistent: upon unsuccessful requests, retain the value (defaults to true, except
35 * for password fields)
37 public function __construct( $params ) {
38 if ( isset( $params['autocomplete'] ) && is_bool( $params['autocomplete'] ) ) {
39 $params['autocomplete'] = $params['autocomplete'] ? 'on' : 'off';
42 parent::__construct( $params );
44 if ( isset( $params['placeholder-message'] ) ) {
45 $this->mPlaceholder = $this->getMessage( $params['placeholder-message'] )->text();
46 } elseif ( isset( $params['placeholder'] ) ) {
47 $this->mPlaceholder = $params['placeholder'];
51 /**
52 * @stable to override
53 * @return int
55 public function getSize() {
56 return $this->mParams['size'] ?? 45;
59 public function getSpellCheck() {
60 $val = $this->mParams['spellcheck'] ?? null;
61 if ( is_bool( $val ) ) {
62 // "spellcheck" attribute literally requires "true" or "false" to work.
63 return $val ? 'true' : 'false';
65 return null;
68 public function isPersistent() {
69 if ( isset( $this->mParams['persistent'] ) ) {
70 return $this->mParams['persistent'];
72 // don't put passwords into the HTML body, they could get cached or otherwise leaked
73 return !( isset( $this->mParams['type'] ) && $this->mParams['type'] === 'password' );
76 /**
77 * @inheritDoc
78 * @stable to override
80 public function getInputHTML( $value ) {
81 if ( !$this->isPersistent() ) {
82 $value = '';
85 $attribs = [
86 'id' => $this->mID,
87 'name' => $this->mName,
88 'size' => $this->getSize(),
89 'value' => $value,
90 'dir' => $this->mDir,
91 'spellcheck' => $this->getSpellCheck(),
92 ] + $this->getTooltipAndAccessKey() + $this->getDataAttribs();
94 if ( $this->mClass !== '' ) {
95 $attribs['class'] = $this->mClass;
97 if ( $this->mPlaceholder !== '' ) {
98 $attribs['placeholder'] = $this->mPlaceholder;
101 # @todo Enforce pattern, step, required, readonly on the server side as
102 # well
103 $allowedParams = [
104 'type',
105 'min',
106 'max',
107 'step',
108 'title',
109 'maxlength',
110 'minlength',
111 'tabindex',
112 'disabled',
113 'required',
114 'autofocus',
115 'readonly',
116 'autocomplete',
117 // Only used in HTML mode:
118 'pattern',
119 'list',
122 $attribs += $this->getAttributes( $allowedParams );
124 # Extract 'type'
125 $type = $this->getType( $attribs );
127 $inputHtml = Html::input( $this->mName, $value, $type, $attribs );
128 return $inputHtml;
131 protected function getType( &$attribs ) {
132 $type = $attribs['type'] ?? 'text';
133 unset( $attribs['type'] );
135 # Implement tiny differences between some field variants
136 # here, rather than creating a new class for each one which
137 # is essentially just a clone of this one.
138 if ( isset( $this->mParams['type'] ) ) {
139 switch ( $this->mParams['type'] ) {
140 case 'int':
141 $type = 'number';
142 $attribs['step'] = 1;
143 break;
144 case 'float':
145 $type = 'number';
146 $attribs['step'] = 'any';
147 break;
148 # Pass through
149 case 'email':
150 case 'password':
151 case 'url':
152 $type = $this->mParams['type'];
153 break;
154 case 'textwithbutton':
155 $type = $this->mParams['inputtype'] ?? 'text';
156 break;
160 return $type;
164 * @inheritDoc
165 * @stable to override
167 public function getInputOOUI( $value ) {
168 if ( !$this->isPersistent() ) {
169 $value = '';
172 $attribs = $this->getTooltipAndAccessKeyOOUI();
174 if ( $this->mClass !== '' ) {
175 $attribs['classes'] = [ $this->mClass ];
177 if ( $this->mPlaceholder !== '' ) {
178 $attribs['placeholder'] = $this->mPlaceholder;
181 # @todo Enforce pattern, step, required, readonly on the server side as
182 # well
183 $allowedParams = [
184 'type',
185 'min',
186 'max',
187 'step',
188 'title',
189 'maxlength',
190 'minlength',
191 'tabindex',
192 'disabled',
193 'required',
194 'autofocus',
195 'readonly',
196 'autocomplete',
197 // Only used in OOUI mode:
198 'autosize',
199 'flags',
200 'indicator',
203 $attribs += \OOUI\Element::configFromHtmlAttributes(
204 $this->getAttributes( $allowedParams )
207 $type = $this->getType( $attribs );
208 if ( isset( $attribs['step'] ) && $attribs['step'] === 'any' ) {
209 $attribs['step'] = null;
212 return $this->getInputWidget( [
213 'id' => $this->mID,
214 'name' => $this->mName,
215 'value' => $value,
216 'type' => $type,
217 'dir' => $this->mDir,
218 ] + $attribs );
221 public function getInputCodex( $value, $hasErrors ) {
222 if ( !$this->isPersistent() ) {
223 $value = '';
226 $attribs = [
227 'id' => $this->mID,
228 'name' => $this->mName,
229 'size' => $this->getSize(),
230 'value' => $value,
231 'dir' => $this->mDir,
232 'spellcheck' => $this->getSpellCheck(),
233 ] + $this->getTooltipAndAccessKey() + $this->getDataAttribs();
235 if ( $this->mPlaceholder !== '' ) {
236 $attribs['placeholder'] = $this->mPlaceholder;
238 $attribs['class'] = $this->mClass ? [ $this->mClass ] : [];
240 $allowedParams = [
241 'type',
242 'min',
243 'max',
244 'step',
245 'title',
246 'maxlength',
247 'minlength',
248 'tabindex',
249 'disabled',
250 'required',
251 'autofocus',
252 'readonly',
253 'autocomplete',
254 'pattern',
255 'list',
258 $attribs += $this->getAttributes( $allowedParams );
260 // Extract 'type'.
261 $type = $this->getType( $attribs );
263 return static::buildCodexComponent( $value, $hasErrors, $type, $this->mName, $attribs );
267 * Build the markup of the Codex component
269 * @param string $value The value to set the input to
270 * @param bool $hasErrors Whether there are validation errors.
271 * @param string $type The input's type attribute
272 * @param string $name The input's name attribute
273 * @param array $inputAttribs Other input attributes
274 * @return string Raw HTML
276 public static function buildCodexComponent( $value, $hasErrors, $type, $name, $inputAttribs ) {
277 // Set up classes for the outer <div>.
278 $wrapperClass = [ 'cdx-text-input' ];
279 if ( $hasErrors ) {
280 $wrapperClass[] = 'cdx-text-input--status-error';
283 $inputAttribs['class'][] = 'cdx-text-input__input';
284 $inputHtml = Html::input( $name, $value, $type, $inputAttribs );
286 return Html::rawElement( 'div', [ 'class' => $wrapperClass ], $inputHtml );
290 * @stable to override
292 * @param array $params
294 * @return Widget
296 protected function getInputWidget( $params ) {
297 return new \OOUI\TextInputWidget( $params );
301 * Returns an array of data-* attributes to add to the field.
302 * @stable to override
304 * @return array
306 protected function getDataAttribs() {
307 return [];
311 /** @deprecated class alias since 1.42 */
312 class_alias( HTMLTextField::class, 'HTMLTextField' );