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