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