68use OOUI\MessageWidget;
70use Psr\Log\LoggerAwareTrait;
71use Psr\Log\NullLogger;
73use UnexpectedValueException;
104 private $languageConverter;
113 private $languageConverterFactory;
116 private $parserFactory;
119 private $skinFactory;
122 private $userGroupManager;
125 private $signatureValidatorFactory;
210 $this->logger =
new NullLogger();
211 $this->languageConverter = $languageConverter;
213 $this->hookRunner =
new HookRunner( $hookContainer );
217 $services =
static function () {
223 : $services()->getUserOptionsManager();
224 $this->languageConverterFactory = $languageConverterFactory ?? $services()->getLanguageConverterFactory();
226 $this->parserFactory = $parserFactory ?? $services()->getParserFactory();
227 $this->skinFactory = $skinFactory ?? $services()->getSkinFactory();
228 $this->userGroupManager = $userGroupManager ?? $services()->getUserGroupManager();
229 $this->signatureValidatorFactory = $signatureValidatorFactory
230 ?? $services()->getSignatureValidatorFactory();
251 OutputPage::setupOOUI(
252 strtolower( $context->
getSkin()->getSkinName() ),
266 $this->hookRunner->onGetPreferences( $user, $preferences );
268 $this->loadPreferenceValues( $user, $context, $preferences );
269 $this->logger->debug(
"Created form descriptor for user '{$user->getName()}'" );
280 foreach ( $descriptor as $name => &
$params ) {
283 if ( ( isset(
$params[
'type'] ) &&
$params[
'type'] ===
'info' ) ||
285 ( isset(
$params[
'class'] ) &&
$params[
'class'] === \HTMLInfoField::class ) ||
286 ( isset(
$params[
'class'] ) &&
$params[
'class'] === HTMLInfoField::class )
288 unset( $descriptor[$name] );
293 foreach (
$params as $key => $value ) {
296 case 'options-message':
299 case 'options-messages':
304 if ( preg_match(
'/-messages?$/', $key ) ) {
321 private function loadPreferenceValues(
User $user,
IContextSource $context, &$defaultPreferences ) {
324 unset( $defaultPreferences[$pref] );
329 $form =
new HTMLForm( $simplified, $context );
331 $disable = !$user->
isAllowed(
'editmyoptions' );
333 $defaultOptions = $this->userOptionsManager->getDefaultOptions( $user );
334 $userOptions = $this->userOptionsManager->getOptions( $user );
335 $this->
applyFilters( $userOptions, $defaultPreferences,
'filterForForm' );
337 foreach ( $simplified as $name => $_ ) {
338 $info = &$defaultPreferences[$name];
340 $info[
'disabled'] =
'disabled';
342 if ( isset( $info[
'default'] ) ) {
346 $field = $form->getField( $name );
347 $globalDefault = $defaultOptions[$name] ??
null;
348 $prefFromUser = static::getPreferenceForField( $name, $field, $userOptions );
353 if ( $prefFromUser !==
null &&
354 $field->validate( $prefFromUser, $this->userOptionsManager->getOptions( $user ) ) ===
true ) {
355 $info[
'default'] = $prefFromUser;
356 } elseif ( $field->validate( $globalDefault, $this->userOptionsManager->getOptions( $user ) ) ===
true ) {
357 $info[
'default'] = $globalDefault;
359 $globalDefault = json_encode( $globalDefault );
360 throw new UnexpectedValueException(
361 "Default '$globalDefault' is invalid for preference $name of user " . $user->
getName()
366 return $defaultPreferences;
380 $val = $userOptions[$name] ??
null;
384 $prefix = $field->mParams[
'prefix'] ?? $name;
386 $keys = array_keys( $field->filterDataForSubmit( [] ) );
387 foreach ( $keys as $key ) {
388 if ( $userOptions[$prefix . $key] ??
false ) {
407 $val = $userOptions[$name] ??
null;
410 if ( ( isset( $info[
'type'] ) && $info[
'type'] ==
'multiselect' ) ||
412 ( isset( $info[
'class'] ) && $info[
'class'] === \HTMLMultiSelectField::class ) ||
413 ( isset( $info[
'class'] ) && $info[
'class'] === HTMLMultiSelectField::class )
415 $options = HTMLFormField::flattenOptions( $info[
'options-messages'] ?? $info[
'options'] );
416 $prefix = $info[
'prefix'] ?? $name;
420 if ( $userOptions[
"$prefix$value"] ??
false ) {
427 if ( ( isset( $info[
'type'] ) && $info[
'type'] ==
'checkmatrix' ) ||
429 ( isset( $info[
'class'] ) && $info[
'class'] === \HTMLCheckMatrix::class ) ||
430 ( isset( $info[
'class'] ) && $info[
'class'] === HTMLCheckMatrix::class )
432 $columns = HTMLFormField::flattenOptions( $info[
'columns'] );
433 $rows = HTMLFormField::flattenOptions( $info[
'rows'] );
434 $prefix = $info[
'prefix'] ?? $name;
437 foreach ( $columns as $column ) {
438 foreach ( $rows as $row ) {
439 if ( $userOptions[
"$prefix$column-$row"] ??
false ) {
440 $val[] =
"$column-$row";
463 $defaultPreferences[
'username'] = [
465 'label-message' => [
'username', $userName ],
466 'default' => $userName,
467 'section' =>
'personal/info',
473 $userEffectiveGroups = array_diff(
474 $this->userGroupManager->getUserEffectiveGroups( $user ),
477 $defaultPreferences[
'usergroups'] = [
479 'label-message' => [
'prefs-memberingroups',
481 'default' =>
function () use ( $user, $userEffectiveGroups, $context, $lang, $userName ) {
482 $userGroupMemberships = $this->userGroupManager->getUserGroupMemberships( $user );
483 $userGroups = $userMembers = $userTempGroups = $userTempMembers = [];
484 foreach ( $userEffectiveGroups as $ueg ) {
485 $groupStringOrObject = $userGroupMemberships[$ueg] ?? $ueg;
487 $userG = UserGroupMembership::getLinkHTML( $groupStringOrObject, $context );
488 $userM = UserGroupMembership::getLinkHTML( $groupStringOrObject, $context, $userName );
497 $userTempGroups[] = $userG;
498 $userTempMembers[] = $userM;
500 $userGroups[] = $userG;
501 $userMembers[] = $userM;
505 sort( $userMembers );
506 sort( $userTempGroups );
507 sort( $userTempMembers );
508 $userGroups = array_merge( $userTempGroups, $userGroups );
509 $userMembers = array_merge( $userTempMembers, $userMembers );
510 return $context->
msg(
'prefs-memberingroups-type' )
511 ->rawParams( $lang->commaList( $userGroups ), $lang->commaList( $userMembers ) )
515 'section' =>
'personal/info',
519 $formattedEditCount = $lang->formatNum( $user->
getEditCount() );
520 $editCount = $this->linkRenderer->makeLink( $contribTitle, $formattedEditCount );
522 $defaultPreferences[
'editcount'] = [
525 'label-message' =>
'prefs-edits',
526 'default' => $editCount,
527 'section' =>
'personal/info',
531 $displayUser = $context->
getUser();
533 $defaultPreferences[
'registrationdate'] = [
535 'label-message' =>
'prefs-registration',
536 'default' => $context->
msg(
537 'prefs-registration-date-time',
538 $lang->userTimeAndDate( $userRegistration, $displayUser ),
539 $lang->userDate( $userRegistration, $displayUser ),
540 $lang->userTime( $userRegistration, $displayUser )
542 'section' =>
'personal/info',
546 $canViewPrivateInfo = $user->
isAllowed(
'viewmyprivateinfo' );
547 $canEditPrivateInfo = $user->
isAllowed(
'editmyprivateinfo' );
550 $defaultPreferences[
'realname'] = [
552 'type' => $canEditPrivateInfo && $this->authManager->allowsPropertyChange(
'realname' )
555 'section' =>
'personal/info',
556 'label-message' =>
'yourrealname',
557 'help-message' =>
'prefs-help-realname',
560 if ( $canEditPrivateInfo && $this->authManager->allowsAuthenticationDataChange(
563 $defaultPreferences[
'password'] = [
566 'default' => (string)
new ButtonWidget( [
570 'label' => $context->
msg(
'prefs-resetpass' )->text(),
572 'label-message' =>
'yourpassword',
575 ? $context->
msg(
'prefs-help-yourpassword',
576 '[[#mw-prefsection-personal-email|{{int:prefs-email}}]]' )->parse()
578 'section' =>
'personal/info',
585 $defaultPreferences[
'prefershttps'] = [
587 'label-message' =>
'tog-prefershttps',
588 'help-message' =>
'prefs-help-prefershttps',
589 'section' =>
'personal/info'
593 $defaultPreferences[
'downloaduserdata'] = [
596 'label-message' =>
'prefs-user-downloaddata-label',
601 '/api.php?action=query&meta=userinfo&uiprop=*&formatversion=2',
603 $context->
msg(
'prefs-user-downloaddata-info' )->text()
605 'help-message' => [
'prefs-user-downloaddata-help-message', urlencode( $user->
getTitleKey() ) ],
606 'section' =>
'personal/info',
609 $defaultPreferences[
'restoreprefs'] = [
612 'label-message' =>
'prefs-user-restoreprefs-label',
617 ->getSubpage(
'reset' )->getLocalURL()
619 $context->
msg(
'prefs-user-restoreprefs-info' )->text()
621 'section' =>
'personal/info',
624 $languages = $this->languageNameUtils->getLanguageNames(
625 LanguageNameUtils::AUTONYMS,
626 LanguageNameUtils::SUPPORTED
629 if ( !array_key_exists( $languageCode, $languages ) ) {
630 $languages[$languageCode] = $languageCode;
636 foreach ( $languages as $code => $name ) {
637 $display = LanguageCode::bcp47( $code ) .
' - ' . $name;
640 $defaultPreferences[
'language'] = [
642 'section' =>
'personal/i18n',
644 'label-message' =>
'yourlanguage',
647 $neutralGenderMessage = $context->
msg(
'gender-notknown' )->escaped() . (
648 !$context->
msg(
'gender-unknown' )->isDisabled()
649 ?
"<br>" . $context->
msg(
'parentheses' )
650 ->params( $context->
msg(
'gender-unknown' )->plain() )
655 $defaultPreferences[
'gender'] = [
657 'section' =>
'personal/i18n',
659 $neutralGenderMessage =>
'unknown',
660 $context->
msg(
'gender-female' )->escaped() =>
'female',
661 $context->
msg(
'gender-male' )->escaped() =>
'male',
663 'label-message' =>
'yourgender',
664 'help-message' =>
'prefs-help-gender',
668 if ( !$this->languageConverterFactory->isConversionDisabled() ) {
670 foreach ( LanguageConverter::$languagesWithVariants as $langCode ) {
671 if ( $langCode == $this->contLang->getCode() ) {
672 if ( !$this->languageConverter->hasVariants() ) {
676 $variants = $this->languageConverter->getVariants();
678 foreach ( $variants as $v ) {
679 $v = str_replace(
'_',
'-', strtolower( $v ) );
680 $variantArray[$v] = $lang->getVariantname( $v,
false );
684 foreach ( $variantArray as $code => $name ) {
685 $display = LanguageCode::bcp47( $code ) .
' - ' . $name;
689 $defaultPreferences[
'variant'] = [
690 'label-message' =>
'yourvariant',
693 'section' =>
'personal/i18n',
694 'help-message' =>
'prefs-help-variant',
697 $defaultPreferences[
"variant-$langCode"] = [
705 $oldsigWikiText = $this->parserFactory->getInstance()->preSaveTransform(
709 ParserOptions::newFromContext( $context )
711 $oldsigHTML = Parser::stripOuterParagraph(
712 $context->
getOutput()->parseAsContent( $oldsigWikiText )
714 $signatureFieldConfig = [];
716 $signature = $this->userOptionsManager->getOption( $user,
'nickname' );
717 $useFancySig = $this->userOptionsManager->getBoolOption( $user,
'fancysig' );
718 if ( $useFancySig && $signature !==
'' ) {
719 $parserOpts = ParserOptions::newFromContext( $context );
720 $validator = $this->signatureValidatorFactory
721 ->newSignatureValidator( $user, $context, $parserOpts );
722 $signatureErrors = $validator->validateSignature( $signature );
723 if ( $signatureErrors ) {
725 $oldsigHTML .=
'<p><strong>' .
730 $context->
msg(
"prefs-signature-invalid-$sigValidation" )->parse() .
735 foreach ( $signatureErrors as &$sigError ) {
736 $sigError =
new HtmlSnippet( $sigError );
739 $signatureFieldConfig = [
740 'warnings' => $sigValidation !==
'disallow' ? $signatureErrors :
null,
741 'errors' => $sigValidation ===
'disallow' ? $signatureErrors :
null,
746 $defaultPreferences[
'oldsig'] = [
751 'default' =>
new FieldLayout(
753 'label' =>
new HtmlSnippet( $oldsigHTML ),
757 'label' =>
new HtmlSnippet( $context->
msg(
'tog-oldsig' )->parse() )
758 ] + $signatureFieldConfig
760 'section' =>
'personal/signature',
762 $defaultPreferences[
'nickname'] = [
763 'type' => $this->authManager->allowsPropertyChange(
'nickname' ) ?
'text' :
'info',
765 'label-message' =>
'yournick',
766 'validation-callback' =>
function ( $signature, $alldata,
HTMLForm $form ) {
769 'section' =>
'personal/signature',
770 'filter-callback' =>
function ( $signature, array $alldata,
HTMLForm $form ) {
774 $defaultPreferences[
'fancysig'] = [
776 'label-message' =>
'tog-fancysig',
778 'help-message' =>
'prefs-help-signature',
779 'section' =>
'personal/signature'
784 if ( $canViewPrivateInfo ) {
787 ?
'prefs-help-email-required'
788 :
'prefs-help-email';
792 $helpMessages[] =
'prefs-help-email-others';
795 $emailAddress = $user->
getEmail() ? htmlspecialchars( $user->
getEmail() ) :
'';
796 if ( $canEditPrivateInfo && $this->authManager->allowsPropertyChange(
'emailaddress' ) ) {
797 $button =
new ButtonWidget( [
802 $context->
msg( $user->
getEmail() ?
'prefs-changeemail' :
'prefs-setemail' )->text(),
805 $emailAddress .= $emailAddress ==
'' ? $button : (
'<br />' . $button );
808 $defaultPreferences[
'emailaddress'] = [
811 'default' => $emailAddress,
812 'label-message' =>
'youremail',
813 'section' =>
'personal/email',
814 'help-messages' => $helpMessages,
819 $disableEmailPrefs =
false;
821 $defaultPreferences[
'requireemail'] = [
823 'label-message' =>
'tog-requireemail',
824 'help-message' =>
'prefs-help-requireemail',
825 'section' =>
'personal/email',
835 $displayUser = $context->
getUser();
837 $time = $lang->userTimeAndDate( $emailTimestamp, $displayUser );
838 $d = $lang->userDate( $emailTimestamp, $displayUser );
839 $t = $lang->userTime( $emailTimestamp, $displayUser );
840 $emailauthenticated = $context->
msg(
'emailauthenticated',
841 $time, $d, $t )->parse() .
'<br />';
842 $emailauthenticationclass =
'mw-email-authenticated';
844 $disableEmailPrefs =
true;
845 $emailauthenticated = $context->
msg(
'emailnotauthenticated' )->parse() .
'<br />' .
848 'label' => $context->
msg(
'emailconfirmlink' )->text(),
850 $emailauthenticationclass =
"mw-email-not-authenticated";
853 $disableEmailPrefs =
true;
854 $emailauthenticated = $context->
msg(
'noemailprefs' )->escaped();
855 $emailauthenticationclass =
'mw-email-none';
858 if ( $canViewPrivateInfo ) {
859 $defaultPreferences[
'emailauthentication'] = [
862 'section' =>
'personal/email',
863 'label-message' =>
'prefs-emailconfirm-label',
864 'default' => $emailauthenticated,
866 'cssclass' => $emailauthenticationclass,
874 $defaultPreferences[
'disablemail'] = [
875 'id' =>
'wpAllowEmail',
878 'section' =>
'personal/email',
879 'label-message' =>
'allowemail',
880 'disabled' => $disableEmailPrefs,
883 $defaultPreferences[
'email-allow-new-users'] = [
884 'id' =>
'wpAllowEmailFromNewUsers',
886 'section' =>
'personal/email',
887 'label-message' =>
'email-allow-new-users-label',
888 'help-message' =>
'prefs-help-email-allow-new-users',
889 'disabled' => $disableEmailPrefs,
890 'disable-if' => [
'!==',
'disablemail',
'1' ],
893 $defaultPreferences[
'ccmeonemails'] = [
895 'section' =>
'personal/email',
896 'label-message' =>
'tog-ccmeonemails',
897 'disabled' => $disableEmailPrefs,
901 $defaultPreferences[
'email-blacklist'] = [
902 'type' =>
'usersmultiselect',
903 'label-message' =>
'email-mutelist-label',
904 'section' =>
'personal/email',
905 'disabled' => $disableEmailPrefs,
906 'filter' => MultiUsernameFilter::class,
907 'excludetemp' =>
true,
913 $defaultPreferences[
'enotifwatchlistpages'] = [
915 'section' =>
'personal/email',
916 'label-message' =>
'tog-enotifwatchlistpages',
917 'disabled' => $disableEmailPrefs,
921 $defaultPreferences[
'enotifusertalkpages'] = [
923 'section' =>
'personal/email',
924 'label-message' =>
'tog-enotifusertalkpages',
925 'disabled' => $disableEmailPrefs,
931 $defaultPreferences[
'enotifminoredits'] = [
933 'section' =>
'personal/email',
934 'label-message' =>
'tog-enotifminoredits',
935 'disabled' => $disableEmailPrefs,
940 $defaultPreferences[
'enotifrevealaddr'] = [
942 'section' =>
'personal/email',
943 'label-message' =>
'tog-enotifrevealaddr',
944 'disabled' => $disableEmailPrefs,
959 $validSkinNames = $this->getValidSkinNames( $user, $context );
960 if ( $validSkinNames ) {
961 $defaultPreferences[
'skin'] = [
965 'section' =>
'rendering/skin',
967 $hideCond = [
'AND' ];
968 foreach ( $validSkinNames as $skinName => $_ ) {
969 $options = $this->skinFactory->getSkinOptions( $skinName );
970 if (
$options[
'responsive'] ??
false ) {
971 $hideCond[] = [
'!==',
'skin', $skinName ];
974 if ( $hideCond === [
'AND' ] ) {
977 $defaultPreferences[
'skin-responsive'] = [
979 'label-message' =>
'prefs-skin-responsive',
980 'section' =>
'rendering/skin/skin-prefs',
981 'help-message' =>
'prefs-help-skin-responsive',
982 'hide-if' => $hideCond,
988 $safeMode = $this->userOptionsManager->getOption( $user,
'forcesafemode' );
992 if ( $allowUserCss || $allowUserJs ) {
994 $defaultPreferences[
'customcssjs-safemode'] = [
998 'section' =>
'rendering/skin',
999 'default' =>
new FieldLayout(
1000 new MessageWidget( [
1001 'label' =>
new HtmlSnippet( $context->
msg(
'prefs-custom-cssjs-safemode' )->parse() ),
1002 'type' =>
'warning',
1010 if ( $allowUserCss ) {
1011 $cssPage = Title::makeTitleSafe(
NS_USER, $userName .
'/common.css' );
1012 $cssLinkText = $context->
msg(
'prefs-custom-css' )->text();
1013 $linkTools[] = $this->linkRenderer->makeLink( $cssPage, $cssLinkText );
1016 if ( $allowUserJs ) {
1017 $jsPage = Title::makeTitleSafe(
NS_USER, $userName .
'/common.js' );
1018 $jsLinkText = $context->
msg(
'prefs-custom-js' )->text();
1019 $linkTools[] = $this->linkRenderer->makeLink( $jsPage, $jsLinkText );
1022 $defaultPreferences[
'commoncssjs'] = [
1025 'default' => $context->
getLanguage()->pipeList( $linkTools ),
1026 'label-message' =>
'prefs-common-config',
1027 'section' =>
'rendering/skin',
1038 $defaultPreferences[
'imagesize'] = [
1041 'label-message' =>
'imagemaxsize',
1042 'section' =>
'rendering/files',
1044 $defaultPreferences[
'thumbsize'] = [
1047 'label-message' =>
'thumbsize',
1048 'section' =>
'rendering/files',
1062 if ( $dateOptions ) {
1063 $defaultPreferences[
'date'] = [
1065 'options' => $dateOptions,
1066 'section' =>
'rendering/dateformat',
1073 $nowlocal =
Xml::element(
'span', [
'id' =>
'wpLocalTime' ],
1074 $lang->userTime( $now, $user ) );
1075 $nowserver = $lang->userTime( $now, $user,
1076 [
'format' =>
false,
'timecorrection' =>
false ] ) .
1077 Html::hidden(
'wpServerTime', (
int)substr( $now, 8, 2 ) * 60 + (
int)substr( $now, 10, 2 ) );
1079 $defaultPreferences[
'nowserver'] = [
1082 'label-message' =>
'servertime',
1083 'default' => $nowserver,
1084 'section' =>
'rendering/timeoffset',
1087 $defaultPreferences[
'nowlocal'] = [
1090 'label-message' =>
'localtime',
1091 'default' => $nowlocal,
1092 'section' =>
'rendering/timeoffset',
1095 $userTimeCorrection = (string)$this->userOptionsManager->getOption( $user,
'timecorrection' );
1100 $userTimeCorrection,
1105 if ( $userTimeCorrectionObj->getCorrectionType() === UserTimeCorrection::OFFSET ) {
1106 $tzDefault = UserTimeCorrection::formatTimezoneOffset( $userTimeCorrectionObj->getTimeOffset() );
1108 $tzDefault = $userTimeCorrectionObj->toString();
1111 $defaultPreferences[
'timecorrection'] = [
1112 'type' =>
'timezone',
1113 'label-message' =>
'timezonelegend',
1114 'default' => $tzDefault,
1116 'section' =>
'rendering/timeoffset',
1117 'id' =>
'wpTimeCorrection',
1118 'filter' => TimezoneFilter::class,
1130 &$defaultPreferences
1133 $defaultPreferences[
'diffonly'] = [
1135 'section' =>
'rendering/diffs',
1136 'label-message' =>
'tog-diffonly',
1138 $defaultPreferences[
'norollbackdiff'] = [
1140 'section' =>
'rendering/diffs',
1141 'label-message' =>
'tog-norollbackdiff',
1143 $defaultPreferences[
'diff-type'] = [
1149 $defaultPreferences[
'underline'] = [
1152 $l10n->
msg(
'underline-never' )->text() => 0,
1153 $l10n->
msg(
'underline-always' )->text() => 1,
1154 $l10n->
msg(
'underline-default' )->text() => 2,
1156 'label-message' =>
'tog-underline',
1157 'section' =>
'rendering/advancedrendering',
1161 $defaultPreferences[
'showhiddencats'] = [
1163 'section' =>
'rendering/advancedrendering',
1164 'label-message' =>
'tog-showhiddencats'
1168 $defaultPreferences[
'showrollbackconfirmation'] = [
1170 'section' =>
'rendering/advancedrendering',
1171 'label-message' =>
'tog-showrollbackconfirmation',
1175 $defaultPreferences[
'forcesafemode'] = [
1177 'section' =>
'rendering/advancedrendering',
1178 'label-message' =>
'tog-forcesafemode',
1179 'help-message' =>
'prefs-help-forcesafemode'
1189 $defaultPreferences[
'editsectiononrightclick'] = [
1191 'section' =>
'editing/advancedediting',
1192 'label-message' =>
'tog-editsectiononrightclick',
1194 $defaultPreferences[
'editondblclick'] = [
1196 'section' =>
'editing/advancedediting',
1197 'label-message' =>
'tog-editondblclick',
1201 $defaultPreferences[
'editfont'] = [
1203 'section' =>
'editing/editor',
1204 'label-message' =>
'editfont-style',
1206 $l10n->
msg(
'editfont-monospace' )->text() =>
'monospace',
1207 $l10n->
msg(
'editfont-sansserif' )->text() =>
'sans-serif',
1208 $l10n->
msg(
'editfont-serif' )->text() =>
'serif',
1213 if ( $user->
isAllowed(
'minoredit' ) ) {
1214 $defaultPreferences[
'minordefault'] = [
1216 'section' =>
'editing/editor',
1217 'label-message' =>
'tog-minordefault',
1221 $defaultPreferences[
'forceeditsummary'] = [
1223 'section' =>
'editing/editor',
1224 'label-message' =>
'tog-forceeditsummary',
1229 $defaultPreferences[
'editrecovery'] = [
1231 'section' =>
'editing/editor',
1232 'label-message' =>
'tog-editrecovery',
1234 'tog-editrecovery-help',
1235 'https://meta.wikimedia.org/wiki/Talk:Community_Wishlist_Survey_2023/Edit-recovery_feature',
1240 $defaultPreferences[
'useeditwarning'] = [
1242 'section' =>
'editing/editor',
1243 'label-message' =>
'tog-useeditwarning',
1246 $defaultPreferences[
'previewonfirst'] = [
1248 'section' =>
'editing/preview',
1249 'label-message' =>
'tog-previewonfirst',
1251 $defaultPreferences[
'previewontop'] = [
1253 'section' =>
'editing/preview',
1254 'label-message' =>
'tog-previewontop',
1256 $defaultPreferences[
'uselivepreview'] = [
1258 'section' =>
'editing/preview',
1259 'label-message' =>
'tog-uselivepreview',
1270 $rcMax = ceil( $rcMaxAge / ( 3600 * 24 ) );
1271 $defaultPreferences[
'rcdays'] = [
1273 'label-message' =>
'recentchangesdays',
1274 'section' =>
'rc/displayrc',
1279 $defaultPreferences[
'rclimit'] = [
1283 'label-message' =>
'recentchangescount',
1284 'help-message' =>
'prefs-help-recentchangescount',
1285 'section' =>
'rc/displayrc',
1286 'filter' => IntvalFilter::class,
1288 $defaultPreferences[
'usenewrc'] = [
1290 'label-message' =>
'tog-usenewrc',
1291 'section' =>
'rc/advancedrc',
1293 $defaultPreferences[
'hideminor'] = [
1295 'label-message' =>
'tog-hideminor',
1296 'section' =>
'rc/changesrc',
1298 $defaultPreferences[
'pst-cssjs'] = [
1301 $defaultPreferences[
'rcfilters-rc-collapsed'] = [
1304 $defaultPreferences[
'rcfilters-wl-collapsed'] = [
1307 $defaultPreferences[
'rcfilters-saved-queries'] = [
1310 $defaultPreferences[
'rcfilters-wl-saved-queries'] = [
1314 $defaultPreferences[
'rcfilters-limit'] = [
1317 $defaultPreferences[
'rcfilters-saved-queries-versionbackup'] = [
1320 $defaultPreferences[
'rcfilters-wl-saved-queries-versionbackup'] = [
1325 $defaultPreferences[
'hidecategorization'] = [
1327 'label-message' =>
'tog-hidecategorization',
1328 'section' =>
'rc/changesrc',
1333 $defaultPreferences[
'hidepatrolled'] = [
1335 'section' =>
'rc/changesrc',
1336 'label-message' =>
'tog-hidepatrolled',
1341 $defaultPreferences[
'newpageshidepatrolled'] = [
1343 'section' =>
'rc/changesrc',
1344 'label-message' =>
'tog-newpageshidepatrolled',
1349 $defaultPreferences[
'shownumberswatching'] = [
1351 'section' =>
'rc/advancedrc',
1352 'label-message' =>
'tog-shownumberswatching',
1356 $defaultPreferences[
'rcenhancedfilters-disable'] = [
1358 'section' =>
'rc/advancedrc',
1359 'label-message' =>
'rcfilters-preference-label',
1360 'help-message' =>
'rcfilters-preference-help',
1374 if ( $user->
isAllowed(
'editmywatchlist' ) ) {
1375 $editWatchlistLinks =
'';
1376 $editWatchlistModes = [
1377 'edit' => [
'subpage' =>
false,
'flags' => [] ],
1378 'raw' => [
'subpage' =>
'raw',
'flags' => [] ],
1379 'clear' => [
'subpage' =>
'clear',
'flags' => [
'destructive' ] ],
1381 foreach ( $editWatchlistModes as $mode =>
$options ) {
1383 $editWatchlistLinks .=
1387 'label' =>
new HtmlSnippet(
1388 $context->
msg(
"prefs-editwatchlist-{$mode}" )->parse()
1393 $defaultPreferences[
'editwatchlist'] = [
1396 'default' => $editWatchlistLinks,
1397 'label-message' =>
'prefs-editwatchlist-label',
1398 'section' =>
'watchlist/editwatchlist',
1402 $defaultPreferences[
'watchlistdays'] = [
1405 'max' => $watchlistdaysMax,
1406 'section' =>
'watchlist/displaywatchlist',
1407 'help-message' => [
'prefs-watchlist-days-max',
Message::numParam( $watchlistdaysMax ) ],
1408 'label-message' =>
'prefs-watchlist-days',
1410 $defaultPreferences[
'wllimit'] = [
1414 'label-message' =>
'prefs-watchlist-edits',
1415 'help-message' =>
'prefs-watchlist-edits-max',
1416 'section' =>
'watchlist/displaywatchlist',
1417 'filter' => IntvalFilter::class,
1419 $defaultPreferences[
'extendwatchlist'] = [
1421 'section' =>
'watchlist/advancedwatchlist',
1422 'label-message' =>
'tog-extendwatchlist',
1424 $defaultPreferences[
'watchlisthideminor'] = [
1426 'section' =>
'watchlist/changeswatchlist',
1427 'label-message' =>
'tog-watchlisthideminor',
1429 $defaultPreferences[
'watchlisthidebots'] = [
1431 'section' =>
'watchlist/changeswatchlist',
1432 'label-message' =>
'tog-watchlisthidebots',
1434 $defaultPreferences[
'watchlisthideown'] = [
1436 'section' =>
'watchlist/changeswatchlist',
1437 'label-message' =>
'tog-watchlisthideown',
1439 $defaultPreferences[
'watchlisthideanons'] = [
1441 'section' =>
'watchlist/changeswatchlist',
1442 'label-message' =>
'tog-watchlisthideanons',
1444 $defaultPreferences[
'watchlisthideliu'] = [
1446 'section' =>
'watchlist/changeswatchlist',
1447 'label-message' =>
'tog-watchlisthideliu',
1451 $defaultPreferences[
'watchlistreloadautomatically'] = [
1453 'section' =>
'watchlist/advancedwatchlist',
1454 'label-message' =>
'tog-watchlistreloadautomatically',
1458 $defaultPreferences[
'watchlistunwatchlinks'] = [
1460 'section' =>
'watchlist/advancedwatchlist',
1461 'label-message' =>
'tog-watchlistunwatchlinks',
1465 $defaultPreferences[
'watchlisthidecategorization'] = [
1467 'section' =>
'watchlist/changeswatchlist',
1468 'label-message' =>
'tog-watchlisthidecategorization',
1473 $defaultPreferences[
'watchlisthidepatrolled'] = [
1475 'section' =>
'watchlist/changeswatchlist',
1476 'label-message' =>
'tog-watchlisthidepatrolled',
1481 'edit' =>
'watchdefault',
1482 'move' =>
'watchmoves',
1486 if ( $user->
isAllowedAny(
'createpage',
'createtalk' ) ) {
1487 $watchTypes[
'read'] =
'watchcreations';
1492 'rollback' =>
'watchrollback',
1493 'upload' =>
'watchuploads',
1494 'delete' =>
'watchdeletion',
1497 foreach ( $watchTypes as $action => $pref ) {
1502 $defaultPreferences[$pref] = [
1504 'section' =>
'watchlist/pageswatchlist',
1505 'label-message' =>
"tog-$pref",
1510 $defaultPreferences[
'watchlisttoken'] = [
1514 $tokenButton =
new ButtonWidget( [
1518 'label' => $context->
msg(
'prefs-watchlist-managetokens' )->text(),
1520 $defaultPreferences[
'watchlisttoken-info'] = [
1522 'section' =>
'watchlist/tokenwatchlist',
1523 'label-message' =>
'prefs-watchlist-token',
1524 'help-message' =>
'prefs-help-tokenmanagement',
1526 'default' => (string)$tokenButton,
1529 $defaultPreferences[
'wlenhancedfilters-disable'] = [
1531 'section' =>
'watchlist/advancedwatchlist',
1532 'label-message' =>
'rcfilters-watchlist-preference-label',
1533 'help-message' =>
'rcfilters-watchlist-preference-help',
1542 $defaultPreferences[
'search-special-page'] = [
1546 foreach ( $this->nsInfo->getValidNamespaces() as $n ) {
1547 $defaultPreferences[
'searchNs' . $n] = [
1553 $defaultPreferences[
'search-match-redirect'] = [
1555 'section' =>
'searchoptions/searchmisc',
1556 'label-message' =>
'search-match-redirect-label',
1557 'help-message' =>
'search-match-redirect-help',
1560 $defaultPreferences[
'search-match-redirect'] = [
1565 $defaultPreferences[
'searchlimit'] = [
1569 'section' =>
'searchoptions/searchmisc',
1570 'label-message' =>
'searchlimit-label',
1571 'help-message' => $context->
msg(
'searchlimit-help', 500 ),
1572 'filter' => IntvalFilter::class,
1578 $thumbNamespacesFormatted = array_combine(
1581 static function ( $namespaceId ) use ( $context ) {
1582 return $namespaceId ===
NS_MAIN
1583 ? $context->
msg(
'blanknamespace' )->escaped()
1584 : $context->
getLanguage()->getFormattedNsText( $namespaceId );
1589 $defaultThumbNamespacesFormatted =
1590 array_intersect_key( $thumbNamespacesFormatted, [
NS_FILE => 1 ] ) ?? [];
1591 $extraThumbNamespacesFormatted =
1592 array_diff_key( $thumbNamespacesFormatted, [
NS_FILE => 1 ] );
1593 if ( $extraThumbNamespacesFormatted ) {
1594 $defaultPreferences[
'search-thumbnail-extra-namespaces'] = [
1596 'section' =>
'searchoptions/searchmisc',
1597 'label-message' =>
'search-thumbnail-extra-namespaces-label',
1598 'help-message' => $context->
msg(
1599 'search-thumbnail-extra-namespaces-message',
1600 $context->
getLanguage()->listToText( $extraThumbNamespacesFormatted ),
1601 count( $extraThumbNamespacesFormatted ),
1602 $context->
getLanguage()->listToText( $defaultThumbNamespacesFormatted ),
1603 count( $defaultThumbNamespacesFormatted )
1618 private static function sortSkinNames( $a, $b, $currentSkin, $preferredSkins ) {
1620 if ( strcasecmp( $a, $currentSkin ) === 0 ) {
1623 if ( strcasecmp( $b, $currentSkin ) === 0 ) {
1627 if ( count( $preferredSkins ) ) {
1628 $aPreferred = array_search( $a, $preferredSkins );
1629 $bPreferred = array_search( $b, $preferredSkins );
1632 if ( $aPreferred !==
false && $bPreferred ===
false ) {
1635 if ( $aPreferred ===
false && $bPreferred !==
false ) {
1640 if ( $aPreferred !==
false && $bPreferred !==
false ) {
1641 return strcasecmp( $aPreferred, $bPreferred );
1645 return strcasecmp( $a, $b );
1656 private function getValidSkinNames( User $user, IContextSource $context ) {
1658 $validSkinNames = $this->skinFactory->getAllowedSkins();
1659 $allInstalledSkins = $this->skinFactory->getInstalledSkins();
1662 $useSkin = $context->getRequest()->getRawVal(
'useskin' );
1663 if ( $useSkin !==
null && isset( $allInstalledSkins[$useSkin] )
1664 && $context->msg(
"skinname-$useSkin" )->exists()
1666 $validSkinNames[$useSkin] = $useSkin;
1670 $currentUserSkin = $this->userOptionsManager->getOption( $user,
'skin' );
1671 if ( isset( $allInstalledSkins[$currentUserSkin] )
1672 && $context->msg(
"skinname-$currentUserSkin" )->exists()
1674 $validSkinNames[$currentUserSkin] = $currentUserSkin;
1677 foreach ( $validSkinNames as $skinkey => &$skinname ) {
1678 $msg = $context->msg(
"skinname-{$skinkey}" );
1679 if ( $msg->exists() ) {
1680 $skinname = htmlspecialchars( $msg->text() );
1687 uksort( $validSkinNames,
function ( $a, $b ) use ( $currentUserSkin, $preferredSkins ) {
1688 return $this->sortSkinNames( $a, $b, $currentUserSkin, $preferredSkins );
1691 return $validSkinNames;
1703 $mptitle = Title::newMainPage();
1704 $previewtext = $context->
msg(
'skin-preview' )->escaped();
1708 $safeMode = $this->userOptionsManager->getOption( $user,
'forcesafemode' );
1709 $foundDefault =
false;
1710 foreach ( $validSkinNames as $skinkey => $sn ) {
1714 if ( strcasecmp( $skinkey, $defaultSkin ) === 0 ) {
1715 $linkTools[] = $context->
msg(
'default' )->escaped();
1716 $foundDefault =
true;
1720 $talkPageMsg = $context->
msg(
"$skinkey-prefs-talkpage" );
1721 if ( $talkPageMsg->exists() ) {
1722 $linkTools[] = $talkPageMsg->parse();
1726 $mplink = htmlspecialchars( $mptitle->getLocalURL( [
'useskin' => $skinkey ] ) );
1727 $linkTools[] =
"<a target='_blank' href=\"$mplink\">$previewtext</a>";
1732 if ( $allowUserCss ) {
1733 $cssPage = Title::makeTitleSafe(
NS_USER, $user->
getName() .
'/' . $skinkey .
'.css' );
1734 $cssLinkText = $context->
msg(
'prefs-custom-css' )->text();
1735 $linkTools[] = $this->linkRenderer->makeLink( $cssPage, $cssLinkText );
1738 if ( $allowUserJs ) {
1739 $jsPage = Title::makeTitleSafe(
NS_USER, $user->
getName() .
'/' . $skinkey .
'.js' );
1740 $jsLinkText = $context->
msg(
'prefs-custom-js' )->text();
1741 $linkTools[] = $this->linkRenderer->makeLink( $jsPage, $jsLinkText );
1745 $display = $sn .
' ' . $context->
msg(
'parentheses' )
1746 ->rawParams( $context->
getLanguage()->pipeList( $linkTools ) )
1748 $ret[$display] = $skinkey;
1751 if ( !$foundDefault ) {
1766 $dateopts = $lang->getDatePreferences();
1771 if ( !in_array(
'default', $dateopts ) ) {
1772 $dateopts[] =
'default';
1782 foreach ( $dateopts as $key ) {
1783 if ( $key ==
'default' ) {
1784 $formatted = $context->
msg(
'datedefault' )->escaped();
1786 $formatted = htmlspecialchars( $lang->timeanddate( $epoch,
false, $key ) );
1788 $ret[$formatted] = $key;
1800 $pixels = $l10n->
msg(
'unit-pixel' )->text();
1804 $display =
"{$limits[0]}\u{200E}×{$limits[1]}$pixels";
1805 $ret[$display] = $index;
1817 $pixels = $l10n->
msg(
'unit-pixel' )->text();
1820 $display = $size . $pixels;
1821 $ret[$display] = $index;
1836 if ( is_string( $signature ) && mb_strlen( $signature ) > $maxSigChars ) {
1837 return $form->
msg(
'badsiglength' )->numParams( $maxSigChars )->escaped();
1840 if ( $signature ===
null || $signature ===
'' ) {
1847 if ( !( isset( $alldata[
'fancysig'] ) && $alldata[
'fancysig'] ) ) {
1864 $signature === $this->userOptionsManager->getOption( $user,
'nickname' ) &&
1865 (
bool)$alldata[
'fancysig'] === $this->userOptionsManager->getBoolOption( $user,
'fancysig' )
1870 if ( $sigValidation ===
'new' || $sigValidation ===
'disallow' ) {
1872 $parserOpts = ParserOptions::newFromContext( $form->
getContext() );
1873 $validator = $this->signatureValidatorFactory
1874 ->newSignatureValidator( $user, $form->
getContext(), $parserOpts );
1875 $errors = $validator->validateSignature( $signature );
1884 if ( $this->parserFactory->getInstance()->validateSig( $signature ) ===
false ) {
1885 return $form->
msg(
'badsig' )->escaped();
1898 if ( isset( $alldata[
'fancysig'] ) && $alldata[
'fancysig'] ) {
1899 $signature = $this->parserFactory->getInstance()->cleanSig( $signature );
1902 $signature = Parser::cleanSigInSig( $signature );
1918 $formClass = PreferencesFormOOUI::class,
1926 if ( count( $remove ) ) {
1927 $removeKeys = array_fill_keys( $remove,
true );
1928 $formDescriptor = array_diff_key( $formDescriptor, $removeKeys );
1932 foreach ( $formDescriptor as $name => $info ) {
1933 if ( isset( $info[
'type'] ) && $info[
'type'] ===
'api' ) {
1934 unset( $formDescriptor[$name] );
1941 $htmlForm =
new $formClass( $formDescriptor, $context,
'prefs' );
1947 $htmlForm->setAction( $context->
getTitle()->getLocalURL( [
1948 'useskin' => $context->
getRequest()->getRawVal(
'useskin' )
1951 $htmlForm->setModifiedUser( $user );
1952 $htmlForm->setOptionsEditable( $user->
isAllowed(
'editmyoptions' ) );
1953 $htmlForm->setPrivateInfoEditable( $user->
isAllowed(
'editmyprivateinfo' ) );
1954 $htmlForm->setId(
'mw-prefs-form' );
1955 $htmlForm->setAutocomplete(
'off' );
1956 $htmlForm->setSubmitTextMsg(
'saveprefs' );
1958 $htmlForm->setSubmitTooltip(
'preferences-save' );
1959 $htmlForm->setSubmitID(
'prefcontrol' );
1960 $htmlForm->setSubmitCallback(
1962 return $this->
submitForm( $formData, $form, $formDescriptor );
1982 if ( !$user->isAllowedAny(
'editmyprivateinfo',
'editmyoptions' ) ) {
1983 return Status::newFatal(
'mypreferencesprotected' );
1987 $this->
applyFilters( $formData, $formDescriptor,
'filterFromForm' );
1992 if ( !in_array(
'realname', $hiddenPrefs )
1993 && $user->isAllowed(
'editmyprivateinfo' )
1994 && array_key_exists(
'realname', $formData )
1996 $realName = $formData[
'realname'];
1997 $user->setRealName( $realName );
2000 if ( $user->isAllowed(
'editmyoptions' ) ) {
2001 $oldUserOptions = $this->userOptionsManager->getOptions( $user );
2004 unset( $formData[$b] );
2010 foreach ( $hiddenPrefs as $pref ) {
2013 $formData[$pref] = $this->userOptionsManager->getOption( $user, $pref,
null,
true );
2018 isset( $formData[
'rclimit'] ) &&
2019 intval( $formData[
'rclimit' ] ) !== $this->userOptionsManager->getIntOption( $user,
'rclimit' )
2021 $formData[
'rcfilters-limit'] = $formData[
'rclimit'];
2026 $this->userOptionsManager->resetOptionsByName( $user, $optionsToReset );
2028 foreach ( $formData as $key => $value ) {
2032 $except = !empty( $formData[$key . UserOptionsLookup::LOCAL_EXCEPTION_SUFFIX] );
2033 $this->userOptionsManager->setOption( $user, $key, $value,
2034 $except ? UserOptionsManager::GLOBAL_OVERRIDE : UserOptionsManager::GLOBAL_IGNORE );
2037 $this->hookRunner->onPreferencesFormPreSave(
2038 $formData, $form, $user, $result, $oldUserOptions );
2041 $user->saveSettings();
2054 protected function applyFilters( array &$preferences, array $formDescriptor, $verb ) {
2055 foreach ( $formDescriptor as $preference => $desc ) {
2056 if ( !isset( $desc[
'filter'] ) || !isset( $preferences[$preference] ) ) {
2059 $filterDesc = $desc[
'filter'];
2060 if ( $filterDesc instanceof
Filter ) {
2061 $filter = $filterDesc;
2062 } elseif ( class_exists( $filterDesc ) ) {
2063 $filter =
new $filterDesc();
2064 } elseif ( is_callable( $filterDesc ) ) {
2065 $filter = $filterDesc();
2067 throw new UnexpectedValueException(
2068 "Unrecognized filter type for preference '$preference'"
2071 $preferences[$preference] = $filter->$verb( $preferences[$preference] );
2086 array $formDescriptor
2088 $res = $this->
saveFormData( $formData, $form, $formDescriptor );
2090 if ( $res ===
true ) {
2099 $context->getRequest()->getSession()->set(
'specialPreferencesSaveSuccess', 1 );
2101 $context->getOutput()->redirect(
$url );
2104 return ( $res ===
true ? Status::newGood() : $res );
2110 $options ??= $this->userOptionsManager->loadUserOptions( $user );
2118 foreach ( $specialOptions as $name => $value ) {
2119 unset( $prefs[$name] );
2124 $multiselectOptions = [];
2125 foreach ( $prefs as $name => $info ) {
2126 if ( ( isset( $info[
'type'] ) && $info[
'type'] ==
'multiselect' ) ||
2128 ( isset( $info[
'class'] ) && $info[
'class'] === \HTMLMultiSelectField::class ) ||
2129 ( isset( $info[
'class'] ) && $info[
'class'] === HTMLMultiSelectField::class )
2131 $opts = HTMLFormField::flattenOptions( $info[
'options'] ?? $info[
'options-messages'] );
2132 $prefix = $info[
'prefix'] ?? $name;
2134 foreach ( $opts as $value ) {
2135 $multiselectOptions[
"$prefix$value"] =
true;
2138 unset( $prefs[$name] );
2141 $checkmatrixOptions = [];
2142 foreach ( $prefs as $name => $info ) {
2143 if ( ( isset( $info[
'type'] ) && $info[
'type'] ==
'checkmatrix' ) ||
2145 ( isset( $info[
'class'] ) && $info[
'class'] === \HTMLCheckMatrix::class ) ||
2146 ( isset( $info[
'class'] ) && $info[
'class'] === HTMLCheckMatrix::class )
2148 $columns = HTMLFormField::flattenOptions( $info[
'columns'] );
2149 $rows = HTMLFormField::flattenOptions( $info[
'rows'] );
2150 $prefix = $info[
'prefix'] ?? $name;
2152 foreach ( $columns as $column ) {
2153 foreach ( $rows as $row ) {
2154 $checkmatrixOptions[
"$prefix$column-$row"] =
true;
2158 unset( $prefs[$name] );
2163 foreach (
$options as $key => $value ) {
2164 if ( isset( $prefs[$key] ) ) {
2165 $mapping[$key] =
'registered';
2166 } elseif ( isset( $multiselectOptions[$key] ) ) {
2167 $mapping[$key] =
'registered-multiselect';
2168 } elseif ( isset( $checkmatrixOptions[$key] ) ) {
2169 $mapping[$key] =
'registered-checkmatrix';
2170 } elseif ( isset( $specialOptions[$key] ) ) {
2171 $mapping[$key] =
'special';
2172 } elseif ( str_starts_with( $key,
'userjs-' ) ) {
2173 $mapping[$key] =
'userjs';
2174 } elseif ( str_starts_with( $key, UserOptionsLookup::LOCAL_EXCEPTION_SUFFIX ) ) {
2175 $mapping[$key] =
'local-exception';
2177 $mapping[$key] =
'unused';
2187 'registered-multiselect',
2188 'registered-checkmatrix',
2196 $oldOptions = $this->userOptionsManager->loadUserOptions( $user, IDBAccessObject::READ_LATEST );
2198 if ( !is_array( $kinds ) ) {
2199 $kinds = [ $kinds ];
2202 if ( in_array(
'all', $kinds ) ) {
2203 return array_keys( $oldOptions );
2205 $optionKinds = $this->getResetKinds( $user, $context );
2206 $kinds = array_intersect( $kinds, $this->listResetKinds() );
2209 foreach ( $oldOptions as $key => $value ) {
2210 if ( in_array( $optionKinds[$key], $kinds ) ) {
2211 $optionNames[] = $key;
2214 return $optionNames;
wfTimestampNow()
Convenience function; returns MediaWiki timestamp for the present time.
array $params
The job parameters.
msg( $key,... $params)
Get a Message object with context set Parameters are the same as wfMessage()
getContext()
Get the base IContextSource object.
A class containing constants representing the names of configuration variables.
const HiddenPrefs
Name constant for the HiddenPrefs setting, for use with Config::get()
const ForceHTTPS
Name constant for the ForceHTTPS setting, for use with Config::get()
const EnotifWatchlist
Name constant for the EnotifWatchlist setting, for use with Config::get()
const MaxSigChars
Name constant for the MaxSigChars setting, for use with Config::get()
const RCMaxAge
Name constant for the RCMaxAge setting, for use with Config::get()
const DefaultSkin
Name constant for the DefaultSkin setting, for use with Config::get()
const EnableUserEmailMuteList
Name constant for the EnableUserEmailMuteList setting, for use with Config::get()
const EnotifRevealEditorAddress
Name constant for the EnotifRevealEditorAddress setting, for use with Config::get()
const EnableUserEmail
Name constant for the EnableUserEmail setting, for use with Config::get()
const SkinsPreferred
Name constant for the SkinsPreferred setting, for use with Config::get()
const EnableEditRecovery
Name constant for the EnableEditRecovery setting, for use with Config::get()
const EmailConfirmToEdit
Name constant for the EmailConfirmToEdit setting, for use with Config::get()
const EnableEmail
Name constant for the EnableEmail setting, for use with Config::get()
const LocalTZoffset
Name constant for the LocalTZoffset setting, for use with Config::get()
const RCShowWatchingUsers
Name constant for the RCShowWatchingUsers setting, for use with Config::get()
const EnotifUserTalk
Name constant for the EnotifUserTalk setting, for use with Config::get()
const AllowUserJs
Name constant for the AllowUserJs setting, for use with Config::get()
const ImageLimits
Name constant for the ImageLimits setting, for use with Config::get()
const SearchMatchRedirectPreference
Name constant for the SearchMatchRedirectPreference setting, for use with Config::get()
const EnotifMinorEdits
Name constant for the EnotifMinorEdits setting, for use with Config::get()
const ScriptPath
Name constant for the ScriptPath setting, for use with Config::get()
const AllowUserCss
Name constant for the AllowUserCss setting, for use with Config::get()
const ThumbLimits
Name constant for the ThumbLimits setting, for use with Config::get()
const SecureLogin
Name constant for the SecureLogin setting, for use with Config::get()
const LanguageCode
Name constant for the LanguageCode setting, for use with Config::get()
const SignatureValidation
Name constant for the SignatureValidation setting, for use with Config::get()
const AllowUserCssPrefs
Name constant for the AllowUserCssPrefs setting, for use with Config::get()
const RCWatchCategoryMembership
Name constant for the RCWatchCategoryMembership setting, for use with Config::get()
const ThumbnailNamespaces
Name constant for the ThumbnailNamespaces setting, for use with Config::get()
const EmailAuthentication
Name constant for the EmailAuthentication setting, for use with Config::get()
This is one of the Core classes and should be read at least once by any new developers.
Parent class for all special pages.
static getTitleFor( $name, $subpage=false, $fragment='')
Get a localised Title object for a specified special page name If you don't need a full Title object,...
Factory class to create Skin objects.
$wgDefaultUserOptions
Config variable stub for the DefaultUserOptions setting, for use by phpdoc and IDEs.
Interface for objects which can provide a MediaWiki context on request.
Interface for localizing messages in MediaWiki.
msg( $key,... $params)
This is the method for getting translated interface messages.