21 protected $mSubSectionBeforeFields =
false;
24 private $modifiedUser;
27 private $privateInfoEditable =
true;
30 private $optionsEditable =
true;
33 private $useMobileLayout;
39 $this->modifiedUser = $user;
46 if ( $this->modifiedUser ===
null ) {
49 return $this->modifiedUser;
57 return $this->privateInfoEditable;
65 $this->privateInfoEditable = $editable;
73 return $this->optionsEditable;
80 $this->optionsEditable = $optionsEditable;
96 $html = Html::rawElement(
'div', [
'id' =>
'preferences' ], $html );
98 return parent::wrapForm( $html );
108 foreach ( $this->mFlatFields as $fieldname => $field ) {
110 $info = $field->mParams;
111 $prefix = $info[
'prefix'] ?? $fieldname;
112 foreach ( $field->filterDataForSubmit( $data[$fieldname] ) as $key => $value ) {
113 $data[
"$prefix$key"] = $value;
115 unset( $data[$fieldname] );
124 $layout = parent::wrapFieldSetSection( $legend, $section, $attributes, $isRoot );
126 $layout->addClasses( [
'mw-prefs-fieldset-wrapper' ] );
127 $layout->removeClasses( [
'oo-ui-panelLayout-framed' ] );
132 private function isMobileLayout(): bool {
133 if ( $this->useMobileLayout === null ) {
134 $skin = $this->getSkin();
135 $this->useMobileLayout =
false;
136 $this->getHookRunner()->onPreferencesGetLayout( $this->useMobileLayout,
137 $skin->getSkinName(), [
'isResponsive' => $skin->isResponsive() ] );
139 return $this->useMobileLayout;
147 if ( $this->isMobileLayout() && $this->getTitle()->isSpecial(
'Preferences' ) ) {
148 foreach ( $descriptor as $_ => &$info ) {
149 if ( isset( $info[
'type'] ) && in_array( $info[
'type'], [
'check',
'toggle' ] ) ) {
150 unset( $info[
'type'] );
151 $info[
'class'] = HTMLToggleSwitchField::class;
152 } elseif ( isset( $info[
'class'] ) && $info[
'class'] === HTMLCheckField::class ) {
153 $info[
'class'] = HTMLToggleSwitchField::class;
157 return parent::addFields( $descriptor );
165 if ( $this->isMobileLayout() ) {
167 $this->getOutput()->addModuleStyles(
169 'oojs-ui.styles.icons-user',
170 'oojs-ui.styles.icons-editing-core',
171 'oojs-ui.styles.icons-editing-advanced',
172 'oojs-ui.styles.icons-wikimediaui',
173 'oojs-ui.styles.icons-content',
174 'oojs-ui.styles.icons-moderation',
175 'oojs-ui.styles.icons-interactions',
176 'oojs-ui.styles.icons-movement',
177 'oojs-ui.styles.icons-wikimedia',
178 'oojs-ui.styles.icons-media',
179 'oojs-ui.styles.icons-accessibility',
180 'oojs-ui.styles.icons-layout',
183 $form = $this->createMobilePreferencesForm();
185 $form = $this->createDesktopPreferencesForm();
188 $header = $this->formatFormHeader();
190 return $header . $form;
200 $legend = parent::getLegend( $key );
201 $this->getHookRunner()->onPreferencesGetLegend( $this, $key, $legend );
210 return array_keys( array_filter( $this->mFieldTree,
'is_array' ) );
217 private function createMobilePreferencesForm() {
218 $sectionButtons = [];
219 $sectionContents = [];
220 $iconNames = $this->getIconNames();
222 foreach ( $this->mFieldTree as $key => $val ) {
223 if ( !is_array( $val ) ) {
224 wfDebug( __METHOD__ .
" encountered a field not attached to a section: '$key'" );
227 $label = $this->getLegend( $key );
229 $this->getHeaderHtml( $key ) .
230 $this->displaySection(
233 "mw-prefsection-$key-"
235 $this->getFooterHtml( $key );
238 $label = (
new OOUI\Tag(
'div' ) )->appendContent(
239 (
new OOUI\Tag(
'h5' ) )->appendContent( $label )->addClasses( [
'mw-prefs-title' ] ),
240 $this->createMobileDescription( $key )
242 $contentDiv = $this->createContentMobile( $key, $label, $content );
244 $sectionButton =
new OOUI\ButtonWidget( [
245 'id' =>
'mw-mobile-prefs-' . $key,
246 'icon' => $iconNames[ $key ] ??
'settings',
247 'label' =>
new OOUI\HtmlSnippet( $label->toString() ),
249 'classes' => [
'mw-mobile-prefsection' ],
252 $sectionButtons[] = $sectionButton;
253 $sectionContents[] = $contentDiv;
256 $buttonGroup =
new OOUI\ButtonGroupWidget( [
257 'classes' => [
'mw-mobile-prefs-sections' ],
260 $buttonGroup->addItems( $sectionButtons );
261 $form = (
new OOUI\Tag(
'div' ) )
262 ->setAttributes( [
'id' =>
'mw-prefs-container' ] )
263 ->addClasses( [
'mw-mobile-prefs-container' ] )
264 ->appendContent( $buttonGroup )
265 ->appendContent( $sectionContents );
274 private function getIconNames() {
276 'personal' =>
'userAvatar',
277 'rendering' =>
'palette',
279 'rc' =>
'recentChanges',
280 'watchlist' =>
'watchlist',
281 'searchoptions' =>
'search',
286 $this->getHookRunner()->onPreferencesGetIcon( $hookIcons );
287 $iconNames += $hookIcons;
297 private function createMobileDescription( $key ) {
298 $prefDescriptionMsg = $this->
msg(
"prefs-description-" . $key );
299 $prefDescription = $prefDescriptionMsg->exists() ? $prefDescriptionMsg->text() :
"";
300 $prefDescriptionElement = (
new OOUI\Tag(
'p' ) )
301 ->appendContent( $prefDescription )
302 ->addClasses( [
'mw-prefs-description' ] );
304 return $prefDescriptionElement;
314 private function createContentMobile( $key, $label, $content ) {
315 $contentDiv = (
new OOUI\Tag(
'div' ) );
316 $contentDiv->addClasses( [
317 'mw-prefs-content-page',
318 'mw-prefs-section-fieldset',
320 $contentDiv->setAttributes( [
321 'id' =>
'mw-mobile-prefs-' . $key
323 $contentBody = (
new OOUI\Tag(
'div' ) )
324 ->addClasses( [
'mw-htmlform-autoinfuse-lazy' ] )
326 'id' =>
'mw-mobile-prefs-' . $key .
'-content'
328 $contentHeader = (
new OOUI\Tag(
'div' ) )->setAttributes( [
329 'id' =>
'mw-mobile-prefs-' . $key .
'-head'
331 $contentHeader->addClasses( [
'mw-prefs-content-head' ] );
332 $contentHeaderTitle = (
new OOUI\Tag(
'h5' ) )->setAttributes( [
333 'id' =>
'mw-mobile-prefs-' . $key .
'-title',
335 $contentHeaderTitle->appendContent( $label )->addClasses( [
'mw-prefs-header-title' ] );
336 $formContent =
new OOUI\Widget( [
337 'content' =>
new OOUI\HtmlSnippet( $content )
339 $hiddenForm = (
new OOUI\Tag(
'div' ) )->appendContent( $formContent );
340 $contentHeader->appendContent( $contentHeaderTitle );
341 $contentBody->appendContent( $contentHeader );
342 $contentBody->appendContent( $hiddenForm );
343 $contentDiv->appendContent( $contentBody );
352 private function createDesktopPreferencesForm() {
354 foreach ( $this->mFieldTree as $key => $val ) {
355 if ( !is_array( $val ) ) {
356 wfDebug( __METHOD__ .
" encountered a field not attached to a section: '$key'" );
359 $label = $this->getLegend( $key );
361 $this->getHeaderHtml( $key ) .
362 $this->displaySection(
365 "mw-prefsection-$key-"
367 $this->getFooterHtml( $key );
369 $tabPanels[] =
new OOUI\TabPanelLayout(
'mw-prefsection-' . $key, [
370 'classes' => [
'mw-htmlform-autoinfuse-lazy' ],
372 'content' =>
new OOUI\FieldsetLayout( [
373 'classes' => [
'mw-prefs-section-fieldset' ],
374 'id' =>
"mw-prefsection-$key",
378 'content' =>
new OOUI\HtmlSnippet( $content )
387 $indexLayout =
new OOUI\IndexLayout( [
390 'autoFocus' =>
false,
391 'classes' => [
'mw-prefs-tabs' ],
393 $indexLayout->addTabPanels( $tabPanels );
395 $form =
new OOUI\PanelLayout( [
398 'classes' => [
'mw-prefs-tabs-wrapper' ],
399 'content' => $indexLayout