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
63 public function validate( $value, $alldata ) {
64 $rows = $this->mParams['rows'];
65 $columns = $this->mParams['columns'];
66
67 // Make sure user-defined validation callback is run
68 $p = parent::validate( $value, $alldata );
69 if ( $p !== true ) {
70 return $p;
71 }
72
73 // Make sure submitted value is an array
74 if ( !is_array( $value ) ) {
75 return false;
76 }
77
78 // If all options are valid, array_intersect of the valid options
79 // and the provided options will return the provided options.
80 $validOptions = [];
81 foreach ( $rows as $rowTag ) {
82 foreach ( $columns as $columnTag ) {
83 $validOptions[] = $columnTag . '-' . $rowTag;
84 }
85 }
86 $validValues = array_intersect( $value, $validOptions );
87 if ( count( $validValues ) == count( $value ) ) {
88 return true;
89 } else {
90 return $this->msg( 'htmlform-select-badoption' );
91 }
92 }
93
104 public function getInputHTML( $value ) {
105 $html = '';
106 $tableContents = '';
107 $rows = $this->mParams['rows'];
108 $columns = $this->mParams['columns'];
109
110 $attribs = $this->getAttributes( [ 'disabled', 'tabindex' ] );
111
112 // Build the column headers
113 $headerContents = Html::rawElement( 'td', [], "\u{00A0}" );
114 foreach ( $columns as $columnLabel => $columnTag ) {
115 $headerContents .= Html::rawElement( 'th', [], $columnLabel );
116 }
117 $thead = Html::rawElement( 'tr', [], "\n$headerContents\n" );
118 $tableContents .= Html::rawElement( 'thead', [], "\n$thead\n" );
119
120 $tooltipClass = 'mw-icon-question';
121 if ( isset( $this->mParams['tooltip-class'] ) ) {
122 $tooltipClass = $this->mParams['tooltip-class'];
123 }
124
125 // Build the options matrix
126 foreach ( $rows as $rowLabel => $rowTag ) {
127 // Append tooltip if configured
128 if ( isset( $this->mParams['tooltips'][$rowLabel] ) ) {
129 $tooltipAttribs = [
130 'class' => "mw-htmlform-tooltip $tooltipClass",
131 'title' => $this->mParams['tooltips'][$rowLabel],
132 'aria-label' => $this->mParams['tooltips'][$rowLabel]
133 ];
134 $rowLabel .= ' ' . Html::element( 'span', $tooltipAttribs, '' );
135 }
136 $rowContents = Html::rawElement( 'td', [], $rowLabel );
137 foreach ( $columns as $columnTag ) {
138 $thisTag = "$columnTag-$rowTag";
139 // Construct the checkbox
140 $thisAttribs = [
141 'id' => "{$this->mID}-$thisTag",
142 'value' => $thisTag,
143 ];
144 $checked = in_array( $thisTag, (array)$value, true );
145 if ( $this->isTagForcedOff( $thisTag ) ) {
146 $checked = false;
147 $thisAttribs['disabled'] = 1;
148 $thisAttribs['class'] = 'checkmatrix-forced checkmatrix-forced-off';
149 } elseif ( $this->isTagForcedOn( $thisTag ) ) {
150 $checked = true;
151 $thisAttribs['disabled'] = 1;
152 $thisAttribs['class'] = 'checkmatrix-forced checkmatrix-forced-on';
153 }
154
155 $checkbox = $this->getOneCheckboxHTML( $checked, $attribs + $thisAttribs );
156
157 $rowContents .= Html::rawElement(
158 'td',
159 [],
160 $checkbox
161 );
162 }
163 $tableContents .= Html::rawElement( 'tr', [], "\n$rowContents\n" );
164 }
165
166 // Put it all in a table
167 $html .= Html::rawElement( 'table',
168 [ 'class' => 'mw-htmlform-matrix' ],
169 Html::rawElement( 'tbody', [], "\n$tableContents\n" ) ) . "\n";
170
171 return $html;
172 }
173
174 public function getInputOOUI( $value ) {
175 $attribs = $this->getAttributes( [ 'disabled', 'tabindex' ] );
176
177 return new \MediaWiki\Widget\CheckMatrixWidget(
178 [
179 'name' => $this->mName,
180 'infusable' => true,
181 'id' => $this->mID,
182 'rows' => $this->mParams['rows'],
183 'columns' => $this->mParams['columns'],
184 'tooltips' => $this->mParams['tooltips'] ?? [],
185 'tooltips-html' => $this->mParams['tooltips-html'] ?? [],
186 'forcedOff' => $this->mParams['force-options-off'] ?? [],
187 'forcedOn' => $this->mParams['force-options-on'] ?? [],
188 'values' => $value,
189 ] + \OOUI\Element::configFromHtmlAttributes( $attribs )
190 );
191 }
192
193 protected function getOneCheckboxHTML( $checked, $attribs ) {
194 return Html::check( "{$this->mName}[]", $checked, $attribs );
195 }
196
197 protected function isTagForcedOff( $tag ) {
198 return isset( $this->mParams['force-options-off'] )
199 && in_array( $tag, $this->mParams['force-options-off'] );
200 }
201
202 protected function isTagForcedOn( $tag ) {
203 return isset( $this->mParams['force-options-on'] )
204 && in_array( $tag, $this->mParams['force-options-on'] );
205 }
206
212 public function loadDataFromRequest( $request ) {
213 if ( $this->isSubmitAttempt( $request ) ) {
214 // Checkboxes are just not added to the request arrays if they're not checked,
215 // so it's perfectly possible for there not to be an entry at all
216 return $request->getArray( $this->mName, [] );
217 } else {
218 // That's ok, the user has not yet submitted the form, so show the defaults
219 return $this->getDefault();
220 }
221 }
222
223 public function getDefault() {
224 return $this->mDefault ?? [];
225 }
226
227 public function filterDataForSubmit( $data ) {
228 $columns = HTMLFormField::flattenOptions( $this->mParams['columns'] );
229 $rows = HTMLFormField::flattenOptions( $this->mParams['rows'] );
230 $res = [];
231 foreach ( $columns as $column ) {
232 foreach ( $rows as $row ) {
233 // Make sure option hasn't been forced
234 $thisTag = "$column-$row";
235 if ( $this->isTagForcedOff( $thisTag ) ) {
236 $res[$thisTag] = false;
237 } elseif ( $this->isTagForcedOn( $thisTag ) ) {
238 $res[$thisTag] = true;
239 } else {
240 $res[$thisTag] = in_array( $thisTag, $data );
241 }
242 }
243 }
244
245 return $res;
246 }
247
248 protected function getOOUIModules() {
249 return [ 'mediawiki.widgets.CheckMatrixWidget' ];
250 }
251
252 protected function shouldInfuseOOUI() {
253 return true;
254 }
255}
256
258class_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.
shouldInfuseOOUI()
Whether the field should be automatically infused.
getInputHTML( $value)
Build a table containing a matrix of checkbox options.
getInputOOUI( $value)
Same as getInputHTML, but returns an OOUI object.
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:57
The WebRequest class encapsulates getting at data passed in the URL or via a POSTed form,...
element(SerializerNode $parent, SerializerNode $node, $contents)