MediaWiki master
HTMLCheckMatrix.php
Go to the documentation of this file.
1<?php
2
4
10
40 private const REQUIRED_PARAMS = [
41 // Required by underlying HTMLFormField
42 'fieldname',
43 // Required by HTMLCheckMatrix
44 'rows',
45 'columns'
46 ];
47
52 public function __construct( $params ) {
53 $missing = array_diff( self::REQUIRED_PARAMS, array_keys( $params ) );
54 if ( $missing ) {
55 throw new HTMLFormFieldRequiredOptionsException( $this, $missing );
56 }
57
58 // The label should always be on a separate line above the options
59 $params['vertical-label'] = true;
60 parent::__construct( $params );
61 }
62
64 public function validate( $value, $alldata ) {
65 $rows = $this->mParams['rows'];
66 $columns = $this->mParams['columns'];
67
68 // Make sure user-defined validation callback is run
69 $p = parent::validate( $value, $alldata );
70 if ( $p !== true ) {
71 return $p;
72 }
73
74 // Make sure submitted value is an array
75 if ( !is_array( $value ) ) {
76 return false;
77 }
78
79 // If all options are valid, array_intersect of the valid options
80 // and the provided options will return the provided options.
81 $validOptions = [];
82 foreach ( $rows as $rowTag ) {
83 foreach ( $columns as $columnTag ) {
84 $validOptions[] = $columnTag . '-' . $rowTag;
85 }
86 }
87 $validValues = array_intersect( $value, $validOptions );
88 if ( count( $validValues ) == count( $value ) ) {
89 return true;
90 } else {
91 return $this->msg( 'htmlform-select-badoption' );
92 }
93 }
94
105 public function getInputHTML( $value ) {
106 $html = '';
107 $tableContents = '';
108 $rows = $this->mParams['rows'];
109 $columns = $this->mParams['columns'];
110
111 $attribs = $this->getAttributes( [ 'disabled', 'tabindex' ] );
112
113 // Build the column headers
114 $headerContents = Html::rawElement( 'td', [], "\u{00A0}" );
115 foreach ( $columns as $columnLabel => $columnTag ) {
116 $headerContents .= Html::rawElement( 'th', [], $columnLabel );
117 }
118 $thead = Html::rawElement( 'tr', [], "\n$headerContents\n" );
119 $tableContents .= Html::rawElement( 'thead', [], "\n$thead\n" );
120
121 $tooltipClass = 'mw-icon-question';
122 if ( isset( $this->mParams['tooltip-class'] ) ) {
123 $tooltipClass = $this->mParams['tooltip-class'];
124 }
125
126 // Build the options matrix
127 foreach ( $rows as $rowLabel => $rowTag ) {
128 // Append tooltip if configured
129 if ( isset( $this->mParams['tooltips'][$rowLabel] ) ) {
130 $tooltipAttribs = [
131 'class' => "mw-htmlform-tooltip $tooltipClass",
132 'title' => $this->mParams['tooltips'][$rowLabel],
133 'aria-label' => $this->mParams['tooltips'][$rowLabel]
134 ];
135 $rowLabel .= ' ' . Html::element( 'span', $tooltipAttribs, '' );
136 }
137 $rowContents = Html::rawElement( 'td', [], $rowLabel );
138 foreach ( $columns as $columnTag ) {
139 $thisTag = "$columnTag-$rowTag";
140 // Construct the checkbox
141 $thisAttribs = [
142 'id' => "{$this->mID}-$thisTag",
143 'value' => $thisTag,
144 ];
145 $checked = in_array( $thisTag, (array)$value, true );
146 if ( $this->isTagForcedOff( $thisTag ) ) {
147 $checked = false;
148 $thisAttribs['disabled'] = 1;
149 $thisAttribs['class'] = 'checkmatrix-forced checkmatrix-forced-off';
150 } elseif ( $this->isTagForcedOn( $thisTag ) ) {
151 $checked = true;
152 $thisAttribs['disabled'] = 1;
153 $thisAttribs['class'] = 'checkmatrix-forced checkmatrix-forced-on';
154 }
155
156 $checkbox = $this->getOneCheckboxHTML( $checked, $attribs + $thisAttribs );
157
158 $rowContents .= Html::rawElement(
159 'td',
160 [],
161 $checkbox
162 );
163 }
164 $tableContents .= Html::rawElement( 'tr', [], "\n$rowContents\n" );
165 }
166
167 // Put it all in a table
168 $html .= Html::rawElement( 'table',
169 [ 'class' => 'mw-htmlform-matrix' ],
170 Html::rawElement( 'tbody', [], "\n$tableContents\n" ) ) . "\n";
171
172 return $html;
173 }
174
176 public function getInputOOUI( $value ) {
177 $attribs = $this->getAttributes( [ 'disabled', 'tabindex' ] );
178
179 return new \MediaWiki\Widget\CheckMatrixWidget(
180 [
181 'name' => $this->mName,
182 'infusable' => true,
183 'id' => $this->mID,
184 'rows' => $this->mParams['rows'],
185 'columns' => $this->mParams['columns'],
186 'tooltips' => $this->mParams['tooltips'] ?? [],
187 'tooltips-html' => $this->mParams['tooltips-html'] ?? [],
188 'forcedOff' => $this->mParams['force-options-off'] ?? [],
189 'forcedOn' => $this->mParams['force-options-on'] ?? [],
190 'values' => $value,
191 ] + \OOUI\Element::configFromHtmlAttributes( $attribs )
192 );
193 }
194
200 protected function getOneCheckboxHTML( $checked, $attribs ) {
201 return Html::check( "{$this->mName}[]", $checked, $attribs );
202 }
203
208 protected function isTagForcedOff( $tag ) {
209 return isset( $this->mParams['force-options-off'] )
210 && in_array( $tag, $this->mParams['force-options-off'] );
211 }
212
217 protected function isTagForcedOn( $tag ) {
218 return isset( $this->mParams['force-options-on'] )
219 && in_array( $tag, $this->mParams['force-options-on'] );
220 }
221
227 public function loadDataFromRequest( $request ) {
228 if ( $this->isSubmitAttempt( $request ) ) {
229 // Checkboxes are just not added to the request arrays if they're not checked,
230 // so it's perfectly possible for there not to be an entry at all
231 return $request->getArray( $this->mName, [] );
232 } else {
233 // That's ok, the user has not yet submitted the form, so show the defaults
234 return $this->getDefault();
235 }
236 }
237
239 public function getDefault() {
240 return $this->mDefault ?? [];
241 }
242
244 public function filterDataForSubmit( $data ) {
245 $columns = HTMLFormField::flattenOptions( $this->mParams['columns'] );
246 $rows = HTMLFormField::flattenOptions( $this->mParams['rows'] );
247 $res = [];
248 foreach ( $columns as $column ) {
249 foreach ( $rows as $row ) {
250 // Make sure option hasn't been forced
251 $thisTag = "$column-$row";
252 if ( $this->isTagForcedOff( $thisTag ) ) {
253 $res[$thisTag] = false;
254 } elseif ( $this->isTagForcedOn( $thisTag ) ) {
255 $res[$thisTag] = true;
256 } else {
257 $res[$thisTag] = in_array( $thisTag, $data );
258 }
259 }
260 }
261
262 return $res;
263 }
264
266 protected function getOOUIModules() {
267 return [ 'mediawiki.widgets.CheckMatrixWidget' ];
268 }
269
271 protected function shouldInfuseOOUI() {
272 return true;
273 }
274}
275
277class_alias( HTMLCheckMatrix::class, 'HTMLCheckMatrix' );
A checkbox matrix Operates similarly to HTMLMultiSelectField, but instead of using an array of option...
getOOUIModules()
Get the list of extra ResourceLoader modules which must be loaded client-side before it's possible to...
filterDataForSubmit( $data)
Support for separating multi-option preferences into multiple preferences Due to lack of array suppor...
validate( $value, $alldata)
Override this function to add specific validation checks on the field input.Don't forget to call pare...
shouldInfuseOOUI()
Whether the field should be automatically infused.Note that all OOUI HTMLForm fields are infusable (y...
getInputHTML( $value)
Build a table containing a matrix of checkbox options.
getInputOOUI( $value)
Same as getInputHTML, but returns an OOUI object.Defaults to false, which getOOUI will interpret as "...
The parent class to generate form fields.
static flattenOptions( $options)
flatten an array of options to a single array, for instance, a set of "<options>" inside "<optgroups>...
getAttributes(array $list)
Returns the given attributes from the parameters.
msg( $key,... $params)
Get a translated interface message.
isSubmitAttempt(WebRequest $request)
Can we assume that the request is an attempt to submit a HTMLForm, as opposed to an attempt to just v...
This class is a collection of static functions that serve two purposes:
Definition Html.php:43
The WebRequest class encapsulates getting at data passed in the URL or via a POSTed form,...
element(SerializerNode $parent, SerializerNode $node, $contents)