Code Coverage |
||||||||||
Lines |
Functions and Methods |
Classes and Traits |
||||||||
Total | |
0.00% |
0 / 153 |
|
0.00% |
0 / 11 |
CRAP | |
0.00% |
0 / 1 |
OOUIHTMLForm | |
0.00% |
0 / 152 |
|
0.00% |
0 / 11 |
2256 | |
0.00% |
0 / 1 |
__construct | |
0.00% |
0 / 3 |
|
0.00% |
0 / 1 |
2 | |||
loadInputFromParameters | |
0.00% |
0 / 3 |
|
0.00% |
0 / 1 |
2 | |||
getButtons | |
0.00% |
0 / 51 |
|
0.00% |
0 / 1 |
210 | |||
wrapFieldSetSection | |
0.00% |
0 / 16 |
|
0.00% |
0 / 1 |
2 | |||
formatField | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
formatSection | |
0.00% |
0 / 10 |
|
0.00% |
0 / 1 |
12 | |||
getErrorsOrWarnings | |
0.00% |
0 / 21 |
|
0.00% |
0 / 1 |
182 | |||
getHeaderHtml | |
0.00% |
0 / 3 |
|
0.00% |
0 / 1 |
6 | |||
formatFormHeader | |
0.00% |
0 / 19 |
|
0.00% |
0 / 1 |
56 | |||
getBody | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
wrapForm | |
0.00% |
0 / 24 |
|
0.00% |
0 / 1 |
12 |
1 | <?php |
2 | |
3 | namespace MediaWiki\HTMLForm; |
4 | |
5 | /** |
6 | * HTML form generation and submission handling, OOUI style. |
7 | * |
8 | * This program is free software; you can redistribute it and/or modify |
9 | * it under the terms of the GNU General Public License as published by |
10 | * the Free Software Foundation; either version 2 of the License, or |
11 | * (at your option) any later version. |
12 | * |
13 | * This program is distributed in the hope that it will be useful, |
14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
16 | * GNU General Public License for more details. |
17 | * |
18 | * You should have received a copy of the GNU General Public License along |
19 | * with this program; if not, write to the Free Software Foundation, Inc., |
20 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. |
21 | * http://www.gnu.org/copyleft/gpl.html |
22 | * |
23 | * @file |
24 | */ |
25 | |
26 | use DomainException; |
27 | use MediaWiki\Html\Html; |
28 | use MediaWiki\Linker\Linker; |
29 | use MediaWiki\Parser\Sanitizer; |
30 | use MediaWiki\Status\Status; |
31 | |
32 | /** |
33 | * Compact stacked vertical format for forms, implemented using OOUI widgets. |
34 | * |
35 | * @stable to extend |
36 | */ |
37 | class OOUIHTMLForm extends HTMLForm { |
38 | private $oouiErrors; |
39 | private $oouiWarnings; |
40 | |
41 | /** |
42 | * @stable to call |
43 | * @inheritDoc |
44 | */ |
45 | public function __construct( $descriptor, $context = null, $messagePrefix = '' ) { |
46 | parent::__construct( $descriptor, $context, $messagePrefix ); |
47 | $this->getOutput()->enableOOUI(); |
48 | $this->getOutput()->addModuleStyles( 'mediawiki.htmlform.ooui.styles' ); |
49 | } |
50 | |
51 | protected $displayFormat = 'ooui'; |
52 | |
53 | public static function loadInputFromParameters( $fieldname, $descriptor, |
54 | HTMLForm $parent = null |
55 | ) { |
56 | $field = parent::loadInputFromParameters( $fieldname, $descriptor, $parent ); |
57 | $field->setShowEmptyLabel( false ); |
58 | return $field; |
59 | } |
60 | |
61 | public function getButtons() { |
62 | $buttons = ''; |
63 | |
64 | if ( $this->mShowSubmit ) { |
65 | $attribs = [ |
66 | 'infusable' => true, |
67 | 'classes' => [ 'mw-htmlform-submit' ], |
68 | 'type' => 'submit', |
69 | 'label' => $this->getSubmitText(), |
70 | 'value' => $this->getSubmitText(), |
71 | 'flags' => $this->mSubmitFlags, |
72 | ]; |
73 | |
74 | if ( isset( $this->mSubmitID ) ) { |
75 | $attribs['id'] = $this->mSubmitID; |
76 | } |
77 | |
78 | if ( isset( $this->mSubmitName ) ) { |
79 | $attribs['name'] = $this->mSubmitName; |
80 | } |
81 | |
82 | if ( isset( $this->mSubmitTooltip ) ) { |
83 | $attribs += [ |
84 | 'title' => Linker::titleAttrib( $this->mSubmitTooltip ), |
85 | 'accessKey' => Linker::accesskey( $this->mSubmitTooltip ), |
86 | ]; |
87 | } |
88 | |
89 | $buttons .= new \OOUI\ButtonInputWidget( $attribs ); |
90 | } |
91 | |
92 | if ( $this->mShowCancel ) { |
93 | $buttons .= new \OOUI\ButtonWidget( [ |
94 | 'label' => $this->msg( 'cancel' )->text(), |
95 | 'href' => $this->getCancelTargetURL(), |
96 | ] ); |
97 | } |
98 | |
99 | foreach ( $this->mButtons as $button ) { |
100 | $attrs = []; |
101 | |
102 | // @phan-suppress-next-line PhanTypePossiblyInvalidDimOffset Always set in HTMLForm::addButton |
103 | if ( $button['attribs'] ) { |
104 | // @phan-suppress-next-line PhanTypePossiblyInvalidDimOffset Always set in HTMLForm::addButton |
105 | $attrs += $button['attribs']; |
106 | } |
107 | |
108 | if ( isset( $button['id'] ) ) { |
109 | $attrs['id'] = $button['id']; |
110 | } |
111 | |
112 | if ( isset( $button['label-message'] ) ) { |
113 | $label = new \OOUI\HtmlSnippet( $this->getMessage( $button['label-message'] )->parse() ); |
114 | } elseif ( isset( $button['label'] ) ) { |
115 | $label = $button['label']; |
116 | } elseif ( isset( $button['label-raw'] ) ) { |
117 | $label = new \OOUI\HtmlSnippet( $button['label-raw'] ); |
118 | } else { |
119 | $label = $button['value']; |
120 | } |
121 | |
122 | $attrs['classes'] = isset( $attrs['class'] ) ? (array)$attrs['class'] : []; |
123 | |
124 | $buttons .= new \OOUI\ButtonInputWidget( [ |
125 | 'type' => 'submit', |
126 | 'name' => $button['name'], |
127 | 'value' => $button['value'], |
128 | 'label' => $label, |
129 | // @phan-suppress-next-line PhanTypePossiblyInvalidDimOffset Always set in HTMLForm::addButton |
130 | 'flags' => $button['flags'], |
131 | // @phan-suppress-next-line PhanTypePossiblyInvalidDimOffset Always set in HTMLForm::addButton |
132 | 'framed' => $button['framed'], |
133 | ] + $attrs ); |
134 | } |
135 | |
136 | if ( !$buttons ) { |
137 | return ''; |
138 | } |
139 | |
140 | return Html::rawElement( 'div', |
141 | [ 'class' => 'mw-htmlform-submit-buttons' ], "\n$buttons" ) . "\n"; |
142 | } |
143 | |
144 | /** |
145 | * @inheritDoc |
146 | * @return \OOUI\PanelLayout |
147 | */ |
148 | protected function wrapFieldSetSection( $legend, $section, $attributes, $isRoot ) { |
149 | // to get a user visible effect, wrap the fieldset into a framed panel layout |
150 | $layout = new \OOUI\PanelLayout( [ |
151 | 'expanded' => false, |
152 | 'padded' => true, |
153 | 'framed' => true, |
154 | ] ); |
155 | |
156 | $layout->appendContent( |
157 | new \OOUI\FieldsetLayout( [ |
158 | 'label' => $legend, |
159 | 'items' => [ |
160 | new \OOUI\Widget( [ |
161 | 'content' => new \OOUI\HtmlSnippet( $section ) |
162 | ] ), |
163 | ], |
164 | ] + $attributes ) |
165 | ); |
166 | return $layout; |
167 | } |
168 | |
169 | /** |
170 | * @inheritDoc |
171 | * @return \OOUI\FieldLayout HTML |
172 | */ |
173 | protected function formatField( HTMLFormField $field, $value ) { |
174 | return $field->getOOUI( $value ); |
175 | } |
176 | |
177 | /** |
178 | * Put a form section together from the individual fields' HTML, merging it and wrapping. |
179 | * @param \OOUI\FieldLayout[] $fieldsHtml Array of outputs from formatField() |
180 | * @param string $sectionName |
181 | * @param bool $anyFieldHasLabel Unused |
182 | * @return string HTML |
183 | */ |
184 | protected function formatSection( array $fieldsHtml, $sectionName, $anyFieldHasLabel ) { |
185 | if ( !$fieldsHtml ) { |
186 | // Do not generate any wrappers for empty sections. Sections may be empty if they only have |
187 | // subsections, but no fields. A legend will still be added in wrapFieldSetSection(). |
188 | return ''; |
189 | } |
190 | |
191 | $html = implode( '', $fieldsHtml ); |
192 | |
193 | if ( $sectionName ) { |
194 | return Html::rawElement( |
195 | 'div', |
196 | [ 'id' => Sanitizer::escapeIdForAttribute( $sectionName ) ], |
197 | $html |
198 | ); |
199 | } |
200 | return $html; |
201 | } |
202 | |
203 | /** |
204 | * @param string|array|Status $elements |
205 | * @param string $elementsType |
206 | * @return string |
207 | */ |
208 | public function getErrorsOrWarnings( $elements, $elementsType ) { |
209 | if ( $elements === '' ) { |
210 | return ''; |
211 | } |
212 | |
213 | if ( !in_array( $elementsType, [ 'error', 'warning' ], true ) ) { |
214 | throw new DomainException( $elementsType . ' is not a valid type.' ); |
215 | } |
216 | $errors = []; |
217 | if ( $elements instanceof Status ) { |
218 | if ( !$elements->isGood() ) { |
219 | foreach ( $elements->getMessages( $elementsType ) as $msg ) { |
220 | $errors[] = $this->getMessage( $msg )->parse(); |
221 | } |
222 | } |
223 | } elseif ( $elementsType === 'error' ) { |
224 | if ( is_array( $elements ) ) { |
225 | foreach ( $elements as $error ) { |
226 | $errors[] = $this->getMessage( $error )->parse(); |
227 | } |
228 | } elseif ( $elements && $elements !== true ) { |
229 | $errors[] = (string)$elements; |
230 | } |
231 | } |
232 | |
233 | foreach ( $errors as &$error ) { |
234 | $error = new \OOUI\HtmlSnippet( $error ); |
235 | } |
236 | |
237 | // Used in formatFormHeader() |
238 | if ( $elementsType === 'error' ) { |
239 | $this->oouiErrors = $errors; |
240 | } else { |
241 | $this->oouiWarnings = $errors; |
242 | } |
243 | return ''; |
244 | } |
245 | |
246 | public function getHeaderHtml( $section = null ) { |
247 | if ( $section === null ) { |
248 | // We handle $this->mHeader elsewhere, in getBody() |
249 | return ''; |
250 | } else { |
251 | return parent::getHeaderHtml( $section ); |
252 | } |
253 | } |
254 | |
255 | protected function formatFormHeader() { |
256 | if ( !( $this->mHeader || $this->oouiErrors || $this->oouiWarnings ) ) { |
257 | return ''; |
258 | } |
259 | $classes = [ |
260 | 'mw-htmlform-ooui-header', |
261 | ...$this->oouiErrors ? [ 'mw-htmlform-ooui-header-errors' ] : [], |
262 | ...$this->oouiWarnings ? [ 'mw-htmlform-ooui-header-warnings' ] : [], |
263 | ]; |
264 | // if there's no header, don't create an (empty) LabelWidget, simply use a placeholder |
265 | if ( $this->mHeader ) { |
266 | $element = new \OOUI\LabelWidget( [ 'label' => new \OOUI\HtmlSnippet( $this->mHeader ) ] ); |
267 | } else { |
268 | $element = new \OOUI\Widget( [] ); |
269 | } |
270 | return new \OOUI\FieldLayout( |
271 | $element, |
272 | [ |
273 | 'align' => 'top', |
274 | 'errors' => $this->oouiErrors, |
275 | 'notices' => $this->oouiWarnings, |
276 | 'classes' => $classes, |
277 | ] |
278 | ); |
279 | } |
280 | |
281 | public function getBody() { |
282 | return $this->formatFormHeader() . parent::getBody(); |
283 | } |
284 | |
285 | public function wrapForm( $html ) { |
286 | if ( is_string( $this->mWrapperLegend ) ) { |
287 | $phpClass = $this->mCollapsible ? CollapsibleFieldsetLayout::class : \OOUI\FieldsetLayout::class; |
288 | $content = new $phpClass( [ |
289 | 'label' => $this->mWrapperLegend, |
290 | 'collapsed' => $this->mCollapsed, |
291 | 'items' => [ |
292 | new \OOUI\Widget( [ |
293 | 'content' => new \OOUI\HtmlSnippet( $html ) |
294 | ] ), |
295 | ], |
296 | ] + \OOUI\Element::configFromHtmlAttributes( $this->mWrapperAttributes ) ); |
297 | } else { |
298 | $content = new \OOUI\HtmlSnippet( $html ); |
299 | } |
300 | |
301 | $form = new \OOUI\FormLayout( $this->getFormAttributes() + [ |
302 | 'classes' => [ 'mw-htmlform', 'mw-htmlform-ooui' ], |
303 | 'content' => $content, |
304 | ] ); |
305 | |
306 | // Include a wrapper for style, if requested. |
307 | $form = new \OOUI\PanelLayout( [ |
308 | 'classes' => [ 'mw-htmlform-ooui-wrapper' ], |
309 | 'expanded' => false, |
310 | 'padded' => $this->mWrapperLegend !== false, |
311 | 'framed' => $this->mWrapperLegend !== false, |
312 | 'content' => $form, |
313 | ] ); |
314 | |
315 | return $form; |
316 | } |
317 | } |
318 | |
319 | /** @deprecated class alias since 1.42 */ |
320 | class_alias( OOUIHTMLForm::class, 'OOUIHTMLForm' ); |