MediaWiki  master
HTMLAutoCompleteSelectField.php
Go to the documentation of this file.
1 <?php
2 
34  protected $autocompleteData = [];
35 
36  public function __construct( $params ) {
37  $params += [
38  'require-match' => false,
39  ];
40 
41  // FIXME B/C, remove in 1.30
42  if (
43  array_key_exists( 'autocomplete', $params )
44  && !array_key_exists( 'autocomplete-data', $params )
45  ) {
46  $params['autocomplete-data'] = $params['autocomplete'];
47  unset( $params['autocomplete'] );
48  }
49  if (
50  array_key_exists( 'autocomplete-messages', $params )
51  && !array_key_exists( 'autocomplete-data-messages', $params )
52  ) {
53  $params['autocomplete-data-messages'] = $params['autocomplete-messages'];
54  unset( $params['autocomplete-messages'] );
55  }
56 
57  parent::__construct( $params );
58 
59  if ( array_key_exists( 'autocomplete-data-messages', $this->mParams ) ) {
60  foreach ( $this->mParams['autocomplete-data-messages'] as $key => $value ) {
61  $key = $this->msg( $key )->plain();
62  $this->autocompleteData[$key] = strval( $value );
63  }
64  } elseif ( array_key_exists( 'autocomplete-data', $this->mParams ) ) {
65  foreach ( $this->mParams['autocomplete-data'] as $key => $value ) {
66  $this->autocompleteData[$key] = strval( $value );
67  }
68  }
69  if ( !is_array( $this->autocompleteData ) || !$this->autocompleteData ) {
70  throw new MWException( 'HTMLAutoCompleteSelectField called without any autocompletions' );
71  }
72 
73  $this->getOptions();
74  if ( $this->mOptions && !in_array( 'other', $this->mOptions, true ) ) {
75  if ( isset( $params['other-message'] ) ) {
76  $msg = $this->getMessage( $params['other-message'] )->text();
77  } elseif ( isset( $params['other'] ) ) {
78  $msg = $params['other'];
79  } else {
80  $msg = wfMessage( 'htmlform-selectorother-other' )->text();
81  }
82  $this->mOptions[$msg] = 'other';
83  }
84  }
85 
86  public function loadDataFromRequest( $request ) {
87  if ( $request->getCheck( $this->mName ) ) {
88  $val = $request->getText( $this->mName . '-select', 'other' );
89 
90  if ( $val === 'other' ) {
91  $val = $request->getText( $this->mName );
92  if ( isset( $this->autocompleteData[$val] ) ) {
93  $val = $this->autocompleteData[$val];
94  }
95  }
96 
97  return $val;
98  } else {
99  return $this->getDefault();
100  }
101  }
102 
103  public function validate( $value, $alldata ) {
104  $p = parent::validate( $value, $alldata );
105 
106  if ( $p !== true ) {
107  return $p;
108  }
109 
110  $validOptions = HTMLFormField::flattenOptions( $this->getOptions() ?: [] );
111 
112  if ( in_array( strval( $value ), $validOptions, true ) ) {
113  return true;
114  } elseif ( in_array( strval( $value ), $this->autocompleteData, true ) ) {
115  return true;
116  } elseif ( $this->mParams['require-match'] ) {
117  return $this->msg( 'htmlform-select-badoption' );
118  }
119 
120  return true;
121  }
122 
123  // FIXME Ewww, this shouldn't be adding any attributes not requested in $list :(
124  public function getAttributes( array $list ) {
125  $attribs = [
126  'type' => 'text',
127  'data-autocomplete' => FormatJson::encode( array_keys( $this->autocompleteData ) ),
128  ] + parent::getAttributes( $list );
129 
130  if ( $this->getOptions() ) {
131  $attribs['data-hide-if'] = FormatJson::encode(
132  [ '!==', $this->mName . '-select', 'other' ]
133  );
134  }
135 
136  return $attribs;
137  }
138 
139  public function getInputHTML( $value ) {
140  $oldClass = $this->mClass;
141  $this->mClass = (array)$this->mClass;
142 
143  $valInSelect = false;
144  $ret = '';
145 
146  if ( $this->getOptions() ) {
147  if ( $value !== false ) {
148  $value = strval( $value );
149  $valInSelect = in_array(
150  $value, HTMLFormField::flattenOptions( $this->getOptions() ), true
151  );
152  }
153 
154  $selected = $valInSelect ? $value : 'other';
155  $select = new XmlSelect( $this->mName . '-select', $this->mID . '-select', $selected );
156  $select->addOptions( $this->getOptions() );
157  $select->setAttribute( 'class', 'mw-htmlform-select-or-other' );
158 
159  if ( !empty( $this->mParams['disabled'] ) ) {
160  $select->setAttribute( 'disabled', 'disabled' );
161  }
162 
163  if ( isset( $this->mParams['tabindex'] ) ) {
164  $select->setAttribute( 'tabindex', $this->mParams['tabindex'] );
165  }
166 
167  $ret = $select->getHTML() . "<br />\n";
168 
169  $this->mClass[] = 'mw-htmlform-hide-if';
170  }
171 
172  if ( $valInSelect ) {
173  $value = '';
174  } else {
175  $key = array_search( strval( $value ), $this->autocompleteData, true );
176  if ( $key !== false ) {
177  $value = $key;
178  }
179  }
180 
181  $this->mClass[] = 'mw-htmlform-autocomplete';
182  $ret .= parent::getInputHTML( $valInSelect ? '' : $value );
183  $this->mClass = $oldClass;
184 
185  return $ret;
186  }
187 
193  public function getInputOOUI( $value ) {
194  // To be implemented, for now override the function from HTMLTextField
195  return false;
196  }
197 }
getOptions()
Fetch the array of options from the field&#39;s parameters.
Class for generating HTML <select> or <datalist> elements.
Definition: XmlSelect.php:26
static encode( $value, $pretty=false, $escaping=0)
Returns the JSON representation of a value.
Definition: FormatJson.php:115
getInputOOUI( $value)
Get the OOUI version of this input.
msg( $key,... $params)
Get a translated interface message.
getMessage( $value)
Turns a *-message parameter (which could be a MessageSpecifier, or a message name, or a name + parameters array) into a Message.
<input> field.
wfMessage( $key,... $params)
This is the function for getting translated interface messages.
Text field for selecting a value from a large list of possible values, with auto-completion and optio...
static flattenOptions( $options)
flatten an array of options to a single array, for instance, a set of "<options>" inside "<optgroups>...