MediaWiki master
PreferencesFormOOUI.php
Go to the documentation of this file.
1<?php
8
15use OOUI\ButtonGroupWidget;
16use OOUI\ButtonWidget;
17use OOUI\FieldsetLayout;
18use OOUI\HtmlSnippet;
19use OOUI\IndexLayout;
20use OOUI\PanelLayout;
21use OOUI\TabPanelLayout;
22use OOUI\Tag;
23use OOUI\Widget;
24
32 protected $mSubSectionBeforeFields = false;
33
35 private $modifiedUser;
36
38 private $privateInfoEditable = true;
39
41 private $optionsEditable = true;
42
44 private $useMobileLayout;
45
49 public function setModifiedUser( $user ) {
50 $this->modifiedUser = $user;
51 }
52
56 public function getModifiedUser() {
57 if ( $this->modifiedUser === null ) {
58 return $this->getUser();
59 } else {
60 return $this->modifiedUser;
61 }
62 }
63
67 public function isPrivateInfoEditable() {
68 return $this->privateInfoEditable;
69 }
70
75 public function setPrivateInfoEditable( $editable ) {
76 $this->privateInfoEditable = $editable;
77 $this->suppressDefaultSubmit( !$this->privateInfoEditable && !$this->optionsEditable );
78 }
79
83 public function areOptionsEditable() {
84 return $this->optionsEditable;
85 }
86
90 public function setOptionsEditable( $optionsEditable ) {
91 $this->optionsEditable = $optionsEditable;
92 $this->suppressDefaultSubmit( !$this->privateInfoEditable && !$this->optionsEditable );
93 }
94
102 return [];
103 }
104
106 public function wrapForm( $html ) {
107 $html = Html::rawElement( 'div', [ 'id' => 'preferences' ], $html );
108
109 return parent::wrapForm( $html );
110 }
111
118 public function filterDataForSubmit( $data ) {
119 foreach ( $this->mFlatFields as $fieldname => $field ) {
120 if ( $field instanceof HTMLNestedFilterable ) {
121 $info = $field->mParams;
122 $prefix = $info['prefix'] ?? $fieldname;
123 foreach ( $field->filterDataForSubmit( $data[$fieldname] ) as $key => $value ) {
124 $data["$prefix$key"] = $value;
125 }
126 unset( $data[$fieldname] );
127 }
128 }
129
130 return $data;
131 }
132
134 protected function wrapFieldSetSection( $legend, $section, $attributes, $isRoot ) {
135 $layout = parent::wrapFieldSetSection( $legend, $section, $attributes, $isRoot );
136
137 $layout->addClasses( [ 'mw-prefs-fieldset-wrapper' ] );
138 $layout->removeClasses( [ 'oo-ui-panelLayout-framed' ] );
139
140 return $layout;
141 }
142
143 private function isMobileLayout(): bool {
144 if ( $this->useMobileLayout === null ) {
145 $skin = $this->getSkin();
146 $this->useMobileLayout = false;
147 $this->getHookRunner()->onPreferencesGetLayout( $this->useMobileLayout,
148 $skin->getSkinName(), [ 'isResponsive' => $skin->isResponsive() ] );
149 }
150 return $this->useMobileLayout;
151 }
152
156 public function addFields( $descriptor ) {
157 // Replace checkbox fields with toggle switches on Special:Preferences
158 if ( $this->isMobileLayout() && $this->getTitle()->isSpecial( 'Preferences' ) ) {
159 foreach ( $descriptor as $_ => &$info ) {
160 if ( isset( $info['type'] ) && in_array( $info['type'], [ 'check', 'toggle' ] ) ) {
161 unset( $info['type'] );
162 $info['class'] = HTMLToggleSwitchField::class;
163 } elseif ( isset( $info['class'] ) && $info['class'] === HTMLCheckField::class ) {
164 $info['class'] = HTMLToggleSwitchField::class;
165 }
166 }
167 }
168 return parent::addFields( $descriptor );
169 }
170
175 public function getBody() {
176 if ( $this->isMobileLayout() ) {
177 // Import the icons used in the mobile view
178 $this->getOutput()->addModuleStyles(
179 [
180 'oojs-ui.styles.icons-user',
181 'oojs-ui.styles.icons-editing-core',
182 'oojs-ui.styles.icons-editing-advanced',
183 'oojs-ui.styles.icons-wikimediaui',
184 'oojs-ui.styles.icons-content',
185 'oojs-ui.styles.icons-moderation',
186 'oojs-ui.styles.icons-interactions',
187 'oojs-ui.styles.icons-movement',
188 'oojs-ui.styles.icons-wikimedia',
189 'oojs-ui.styles.icons-media',
190 'oojs-ui.styles.icons-accessibility',
191 'oojs-ui.styles.icons-layout',
192 ]
193 );
194 $form = $this->createMobilePreferencesForm();
195 } else {
196 $form = $this->createDesktopPreferencesForm();
197 }
198
199 $header = $this->formatFormHeader();
200
201 return $header . $form;
202 }
203
210 public function getLegend( $key ) {
211 $legend = parent::getLegend( $key );
212 $this->getHookRunner()->onPreferencesGetLegend( $this, $key, $legend );
213 return $legend;
214 }
215
220 public function getPreferenceSections() {
221 return array_keys( array_filter( $this->mFieldTree, 'is_array' ) );
222 }
223
228 private function createMobilePreferencesForm() {
229 $sectionButtons = [];
230 $sectionContents = [];
231 $iconNames = $this->getIconNames();
232
233 foreach ( $this->mFieldTree as $key => $val ) {
234 if ( !is_array( $val ) ) {
235 wfDebug( __METHOD__ . " encountered a field not attached to a section: '$key'" );
236 continue;
237 }
238 $label = $this->getLegend( $key );
239 $content =
240 $this->getHeaderHtml( $key ) .
241 $this->displaySection(
242 $val,
243 "",
244 "mw-prefsection-$key-"
245 ) .
246 $this->getFooterHtml( $key );
247
248 // Creating the header section
249 $label = ( new Tag( 'div' ) )->appendContent(
250 ( new Tag( 'h5' ) )->appendContent( $label )->addClasses( [ 'mw-prefs-title' ] ),
251 $this->createMobileDescription( $key )
252 );
253 $contentDiv = $this->createContentMobile( $key, $label, $content );
254
255 $sectionButton = new ButtonWidget( [
256 'id' => 'mw-mobile-prefs-' . $key,
257 'icon' => $iconNames[ $key ] ?? 'settings',
258 'label' => new HtmlSnippet( $label->toString() ),
259 'data' => $key,
260 'classes' => [ 'mw-mobile-prefsection' ],
261 'framed' => false,
262 ] );
263 $sectionButtons[] = $sectionButton;
264 $sectionContents[] = $contentDiv;
265 }
266
267 $buttonGroup = new ButtonGroupWidget( [
268 'classes' => [ 'mw-mobile-prefs-sections' ],
269 'infusable' => true,
270 ] );
271 $buttonGroup->addItems( $sectionButtons );
272 $form = ( new Tag( 'div' ) )
273 ->setAttributes( [ 'id' => 'mw-prefs-container' ] )
274 ->addClasses( [ 'mw-mobile-prefs-container' ] )
275 ->appendContent( $buttonGroup )
276 ->appendContent( $sectionContents );
277
278 return $form;
279 }
280
285 private function getIconNames() {
286 $iconNames = [
287 'personal' => 'userAvatar',
288 'rendering' => 'palette',
289 'editing' => 'edit',
290 'rc' => 'recentChanges',
291 'watchlist' => 'watchlist',
292 'searchoptions' => 'search',
293 'misc' => '',
294 ];
295 $hookIcons = [];
296 // Get icons from extensions that have their own sections
297 $this->getHookRunner()->onPreferencesGetIcon( $hookIcons );
298 $iconNames += $hookIcons;
299
300 return $iconNames;
301 }
302
308 private function createMobileDescription( $key ) {
309 $prefDescriptionMsg = $this->msg( "prefs-description-" . $key );
310 $prefDescription = $prefDescriptionMsg->exists() ? $prefDescriptionMsg->text() : "";
311 $prefDescriptionElement = ( new Tag( 'p' ) )
312 ->appendContent( $prefDescription )
313 ->addClasses( [ 'mw-prefs-description' ] );
314
315 return $prefDescriptionElement;
316 }
317
325 private function createContentMobile( $key, $label, $content ) {
326 $contentDiv = ( new Tag( 'div' ) );
327 $contentDiv->addClasses( [
328 'mw-prefs-content-page',
329 'mw-prefs-section-fieldset',
330 ] );
331 $contentDiv->setAttributes( [
332 'id' => 'mw-mobile-prefs-' . $key
333 ] );
334 $contentBody = ( new Tag( 'div' ) )
335 ->addClasses( [ 'mw-htmlform-autoinfuse-lazy' ] )
336 ->setAttributes( [
337 'id' => 'mw-mobile-prefs-' . $key . '-content'
338 ] );
339 $contentHeader = ( new Tag( 'div' ) )->setAttributes( [
340 'id' => 'mw-mobile-prefs-' . $key . '-head'
341 ] );
342 $contentHeader->addClasses( [ 'mw-prefs-content-head' ] );
343 $contentHeaderTitle = ( new Tag( 'h5' ) )->setAttributes( [
344 'id' => 'mw-mobile-prefs-' . $key . '-title',
345 ] );
346 $contentHeaderTitle->appendContent( $label )->addClasses( [ 'mw-prefs-header-title' ] );
347 $formContent = new Widget( [
348 'content' => new HtmlSnippet( $content )
349 ] );
350 $hiddenForm = ( new Tag( 'div' ) )->appendContent( $formContent );
351 $contentHeader->appendContent( $contentHeaderTitle );
352 $contentBody->appendContent( $contentHeader );
353 $contentBody->appendContent( $hiddenForm );
354 $contentDiv->appendContent( $contentBody );
355
356 return $contentDiv;
357 }
358
363 private function createDesktopPreferencesForm() {
364 $tabPanels = [];
365 foreach ( $this->mFieldTree as $key => $val ) {
366 if ( !is_array( $val ) ) {
367 wfDebug( __METHOD__ . " encountered a field not attached to a section: '$key'" );
368 continue;
369 }
370 $label = $this->getLegend( $key );
371 $content =
372 $this->getHeaderHtml( $key ) .
373 $this->displaySection(
374 $val,
375 "",
376 "mw-prefsection-$key-"
377 ) .
378 $this->getFooterHtml( $key );
379
380 $tabPanels[] = new TabPanelLayout( 'mw-prefsection-' . $key, [
381 'classes' => [ 'mw-htmlform-autoinfuse-lazy' ],
382 'label' => $label,
383 'content' => new FieldsetLayout( [
384 'classes' => [ 'mw-prefs-section-fieldset' ],
385 'id' => "mw-prefsection-$key",
386 'label' => $label,
387 'items' => [
388 new Widget( [
389 'content' => new HtmlSnippet( $content )
390 ] ),
391 ],
392 ] ),
393 'expanded' => false,
394 'framed' => true,
395 ] );
396 }
397
398 $indexLayout = new IndexLayout( [
399 'infusable' => true,
400 'expanded' => false,
401 'autoFocus' => false,
402 'classes' => [ 'mw-prefs-tabs' ],
403 ] );
404 $indexLayout->addTabPanels( $tabPanels );
405
406 $form = new PanelLayout( [
407 'framed' => true,
408 'expanded' => false,
409 'classes' => [ 'mw-prefs-tabs-wrapper' ],
410 'content' => $indexLayout
411 ] );
412
413 return $form;
414 }
415}
416
418class_alias( PreferencesFormOOUI::class, 'PreferencesFormOOUI' );
wfDebug( $text, $dest='all', array $context=[])
Sends a line to the debug log if enabled or, optionally, to a comment in output.
if(!defined('MW_SETUP_CALLBACK'))
Definition WebStart.php:69
suppressDefaultSubmit( $suppressSubmit=true)
Stop a default submit button being shown for this form.
Compact stacked vertical format for forms, implemented using OOUI widgets.
This class is a collection of static functions that serve two purposes:
Definition Html.php:44
wrapForm( $html)
Wrap the form innards in an actual "<form>" element.to override string|\OOUI\Tag Wrapped HTML.
addFields( $descriptor)
Add fields to the form.1.34$this
wrapFieldSetSection( $legend, $section, $attributes, $isRoot)
Wraps the given $section into a user-visible fieldset.to overridestring The fieldset's Html\OOUI\Pane...
getLegend( $key)
Get the "<legend>" for a given section key.
filterDataForSubmit( $data)
Separate multi-option preferences into multiple preferences, since we have to store them separately.
getPreferenceSections()
Get the keys of each top level preference section.
bool $mSubSectionBeforeFields
Override default value from HTMLForm.
getExtraSuccessRedirectParameters()
Get extra parameters for the query string when redirecting after successful save.
User class for the MediaWiki software.
Definition User.php:130
msg( $key,... $params)