70use Psr\Log\LoggerAwareTrait;
71use Psr\Log\NullLogger;
73use UnexpectedValueException;
103 private $languageConverter;
112 private $languageConverterFactory;
115 private $parserFactory;
118 private $skinFactory;
121 private $userGroupManager;
124 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',
576 ? $context->
msg(
'prefs-help-yourpassword',
577 '[[#mw-prefsection-personal-email|{{int:prefs-email}}]]' )->parse()
579 'section' =>
'personal/info',
586 $defaultPreferences[
'prefershttps'] = [
588 'label-message' =>
'tog-prefershttps',
589 'help-message' =>
'prefs-help-prefershttps',
590 'section' =>
'personal/info'
594 $defaultPreferences[
'downloaduserdata'] = [
597 'label-message' =>
'prefs-user-downloaddata-label',
602 '/api.php?action=query&meta=userinfo&uiprop=*&formatversion=2',
604 $context->
msg(
'prefs-user-downloaddata-info' )->text()
606 'help-message' => [
'prefs-user-downloaddata-help-message', urlencode( $user->
getTitleKey() ) ],
607 'section' =>
'personal/info',
610 $defaultPreferences[
'restoreprefs'] = [
613 'label-message' =>
'prefs-user-restoreprefs-label',
618 ->getSubpage(
'reset' )->getLocalURL()
620 $context->
msg(
'prefs-user-restoreprefs-info' )->text()
622 'section' =>
'personal/info',
625 $languages = $this->languageNameUtils->getLanguageNames(
626 LanguageNameUtils::AUTONYMS,
627 LanguageNameUtils::SUPPORTED
630 if ( !array_key_exists( $languageCode, $languages ) ) {
631 $languages[$languageCode] = $languageCode;
637 foreach ( $languages as $code => $name ) {
638 $display = LanguageCode::bcp47( $code ) .
' - ' . $name;
641 $defaultPreferences[
'language'] = [
643 'section' =>
'personal/i18n',
645 'label-message' =>
'yourlanguage',
648 $neutralGenderMessage = $context->
msg(
'gender-notknown' )->escaped() . (
649 !$context->
msg(
'gender-unknown' )->isDisabled()
650 ?
"<br>" . $context->
msg(
'parentheses' )
651 ->params( $context->
msg(
'gender-unknown' )->plain() )
656 $defaultPreferences[
'gender'] = [
658 'section' =>
'personal/i18n',
660 $neutralGenderMessage =>
'unknown',
661 $context->
msg(
'gender-female' )->escaped() =>
'female',
662 $context->
msg(
'gender-male' )->escaped() =>
'male',
664 'label-message' =>
'yourgender',
665 'help-message' =>
'prefs-help-gender',
669 if ( !$this->languageConverterFactory->isConversionDisabled() ) {
671 foreach ( LanguageConverter::$languagesWithVariants as $langCode ) {
672 if ( $langCode == $this->contLang->getCode() ) {
673 if ( !$this->languageConverter->hasVariants() ) {
677 $variants = $this->languageConverter->getVariants();
679 foreach ( $variants as $v ) {
680 $v = str_replace(
'_',
'-', strtolower( $v ) );
681 $variantArray[$v] = $lang->getVariantname( $v,
false );
685 foreach ( $variantArray as $code => $name ) {
686 $display = LanguageCode::bcp47( $code ) .
' - ' . $name;
690 $defaultPreferences[
'variant'] = [
691 'label-message' =>
'yourvariant',
694 'section' =>
'personal/i18n',
695 'help-message' =>
'prefs-help-variant',
698 $defaultPreferences[
"variant-$langCode"] = [
706 $oldsigWikiText = $this->parserFactory->getInstance()->preSaveTransform(
710 ParserOptions::newFromContext( $context )
712 $oldsigHTML = Parser::stripOuterParagraph(
713 $context->
getOutput()->parseAsContent( $oldsigWikiText )
715 $signatureFieldConfig = [];
717 $signature = $this->userOptionsManager->getOption( $user,
'nickname' );
718 $useFancySig = $this->userOptionsManager->getBoolOption( $user,
'fancysig' );
719 if ( $useFancySig && $signature !==
'' ) {
720 $parserOpts = ParserOptions::newFromContext( $context );
721 $validator = $this->signatureValidatorFactory
722 ->newSignatureValidator( $user, $context, $parserOpts );
723 $signatureErrors = $validator->validateSignature( $signature );
724 if ( $signatureErrors ) {
726 $oldsigHTML .=
'<p><strong>' .
731 $context->
msg(
"prefs-signature-invalid-$sigValidation" )->parse() .
736 foreach ( $signatureErrors as &$sigError ) {
737 $sigError =
new HtmlSnippet( $sigError );
740 $signatureFieldConfig = [
741 'warnings' => $sigValidation !==
'disallow' ? $signatureErrors :
null,
742 'errors' => $sigValidation ===
'disallow' ? $signatureErrors :
null,
747 $defaultPreferences[
'oldsig'] = [
752 'default' =>
new FieldLayout(
754 'label' =>
new HtmlSnippet( $oldsigHTML ),
758 'label' =>
new HtmlSnippet( $context->
msg(
'tog-oldsig' )->parse() )
759 ] + $signatureFieldConfig
761 'section' =>
'personal/signature',
763 $defaultPreferences[
'nickname'] = [
764 'type' => $this->authManager->allowsPropertyChange(
'nickname' ) ?
'text' :
'info',
766 'label-message' =>
'yournick',
767 'validation-callback' =>
function ( $signature, $alldata,
HTMLForm $form ) {
770 'section' =>
'personal/signature',
771 'filter-callback' =>
function ( $signature, array $alldata,
HTMLForm $form ) {
775 $defaultPreferences[
'fancysig'] = [
777 'label-message' =>
'tog-fancysig',
779 'help-message' =>
'prefs-help-signature',
780 'section' =>
'personal/signature'
785 if ( $canViewPrivateInfo ) {
788 ?
'prefs-help-email-required'
789 :
'prefs-help-email';
793 $helpMessages[] =
'prefs-help-email-others';
796 $emailAddress = $user->
getEmail() ? htmlspecialchars( $user->
getEmail() ) :
'';
797 if ( $canEditPrivateInfo && $this->authManager->allowsPropertyChange(
'emailaddress' ) ) {
798 $button =
new ButtonWidget( [
803 $context->
msg( $user->
getEmail() ?
'prefs-changeemail' :
'prefs-setemail' )->text(),
806 $emailAddress .= $emailAddress ==
'' ? $button : (
'<br />' . $button );
809 $defaultPreferences[
'emailaddress'] = [
812 'default' => $emailAddress,
813 'label-message' =>
'youremail',
814 'section' =>
'personal/email',
815 'help-messages' => $helpMessages,
820 $disableEmailPrefs =
false;
823 $defaultPreferences[
'requireemail'] = [
825 'label-message' =>
'tog-requireemail',
826 'help-message' =>
'prefs-help-requireemail',
827 'section' =>
'personal/email',
838 $displayUser = $context->
getUser();
840 $time = $lang->userTimeAndDate( $emailTimestamp, $displayUser );
841 $d = $lang->userDate( $emailTimestamp, $displayUser );
842 $t = $lang->userTime( $emailTimestamp, $displayUser );
843 $emailauthenticated = $context->
msg(
'emailauthenticated',
844 $time, $d, $t )->parse() .
'<br />';
845 $emailauthenticationclass =
'mw-email-authenticated';
847 $disableEmailPrefs =
true;
848 $emailauthenticated = $context->
msg(
'emailnotauthenticated' )->parse() .
'<br />' .
851 'label' => $context->
msg(
'emailconfirmlink' )->text(),
853 $emailauthenticationclass =
"mw-email-not-authenticated";
856 $disableEmailPrefs =
true;
857 $emailauthenticated = $context->
msg(
'noemailprefs' )->escaped();
858 $emailauthenticationclass =
'mw-email-none';
861 if ( $canViewPrivateInfo ) {
862 $defaultPreferences[
'emailauthentication'] = [
865 'section' =>
'personal/email',
866 'label-message' =>
'prefs-emailconfirm-label',
867 'default' => $emailauthenticated,
869 'cssclass' => $emailauthenticationclass,
877 $defaultPreferences[
'disablemail'] = [
878 'id' =>
'wpAllowEmail',
881 'section' =>
'personal/email',
882 'label-message' =>
'allowemail',
883 'disabled' => $disableEmailPrefs,
886 $defaultPreferences[
'email-allow-new-users'] = [
887 'id' =>
'wpAllowEmailFromNewUsers',
889 'section' =>
'personal/email',
890 'label-message' =>
'email-allow-new-users-label',
891 'disabled' => $disableEmailPrefs,
892 'disable-if' => [
'!==',
'disablemail',
'1' ],
895 $defaultPreferences[
'ccmeonemails'] = [
897 'section' =>
'personal/email',
898 'label-message' =>
'tog-ccmeonemails',
899 'disabled' => $disableEmailPrefs,
903 $defaultPreferences[
'email-blacklist'] = [
904 'type' =>
'usersmultiselect',
905 'label-message' =>
'email-mutelist-label',
906 'section' =>
'personal/email',
907 'disabled' => $disableEmailPrefs,
908 'filter' => MultiUsernameFilter::class,
914 $defaultPreferences[
'enotifwatchlistpages'] = [
916 'section' =>
'personal/email',
917 'label-message' =>
'tog-enotifwatchlistpages',
918 'disabled' => $disableEmailPrefs,
922 $defaultPreferences[
'enotifusertalkpages'] = [
924 'section' =>
'personal/email',
925 'label-message' =>
'tog-enotifusertalkpages',
926 'disabled' => $disableEmailPrefs,
932 $defaultPreferences[
'enotifminoredits'] = [
934 'section' =>
'personal/email',
935 'label-message' =>
'tog-enotifminoredits',
936 'disabled' => $disableEmailPrefs,
941 $defaultPreferences[
'enotifrevealaddr'] = [
943 'section' =>
'personal/email',
944 'label-message' =>
'tog-enotifrevealaddr',
945 'disabled' => $disableEmailPrefs,
960 $validSkinNames = $this->getValidSkinNames( $user, $context );
961 if ( $validSkinNames ) {
962 $defaultPreferences[
'skin'] = [
966 'section' =>
'rendering/skin',
968 $hideCond = [
'AND' ];
969 foreach ( $validSkinNames as $skinName => $_ ) {
970 $options = $this->skinFactory->getSkinOptions( $skinName );
971 if (
$options[
'responsive'] ??
false ) {
972 $hideCond[] = [
'!==',
'skin', $skinName ];
975 if ( $hideCond === [
'AND' ] ) {
978 $defaultPreferences[
'skin-responsive'] = [
980 'label-message' =>
'prefs-skin-responsive',
981 'section' =>
'rendering/skin/skin-prefs',
982 'help-message' =>
'prefs-help-skin-responsive',
983 'hide-if' => $hideCond,
989 $safeMode = $this->userOptionsManager->getOption( $user,
'forcesafemode' );
993 if ( $allowUserCss || $allowUserJs ) {
995 $defaultPreferences[
'customcssjs-safemode'] = [
998 'default' => Html::warningBox( $context->
msg(
'prefs-custom-cssjs-safemode' )->parse() ),
999 'section' =>
'rendering/skin',
1005 if ( $allowUserCss ) {
1006 $cssPage = Title::makeTitleSafe(
NS_USER, $userName .
'/common.css' );
1007 $cssLinkText = $context->
msg(
'prefs-custom-css' )->text();
1008 $linkTools[] = $this->linkRenderer->makeLink( $cssPage, $cssLinkText );
1011 if ( $allowUserJs ) {
1012 $jsPage = Title::makeTitleSafe(
NS_USER, $userName .
'/common.js' );
1013 $jsLinkText = $context->
msg(
'prefs-custom-js' )->text();
1014 $linkTools[] = $this->linkRenderer->makeLink( $jsPage, $jsLinkText );
1017 $defaultPreferences[
'commoncssjs'] = [
1020 'default' => $context->
getLanguage()->pipeList( $linkTools ),
1021 'label-message' =>
'prefs-common-config',
1022 'section' =>
'rendering/skin',
1033 $defaultPreferences[
'imagesize'] = [
1036 'label-message' =>
'imagemaxsize',
1037 'section' =>
'rendering/files',
1039 $defaultPreferences[
'thumbsize'] = [
1042 'label-message' =>
'thumbsize',
1043 'section' =>
'rendering/files',
1057 if ( $dateOptions ) {
1058 $defaultPreferences[
'date'] = [
1060 'options' => $dateOptions,
1061 'section' =>
'rendering/dateformat',
1068 $nowlocal =
Xml::element(
'span', [
'id' =>
'wpLocalTime' ],
1069 $lang->userTime( $now, $user ) );
1070 $nowserver = $lang->userTime( $now, $user,
1071 [
'format' =>
false,
'timecorrection' =>
false ] ) .
1072 Html::hidden(
'wpServerTime', (
int)substr( $now, 8, 2 ) * 60 + (
int)substr( $now, 10, 2 ) );
1074 $defaultPreferences[
'nowserver'] = [
1077 'label-message' =>
'servertime',
1078 'default' => $nowserver,
1079 'section' =>
'rendering/timeoffset',
1082 $defaultPreferences[
'nowlocal'] = [
1085 'label-message' =>
'localtime',
1086 'default' => $nowlocal,
1087 'section' =>
'rendering/timeoffset',
1090 $userTimeCorrection = (string)$this->userOptionsManager->getOption( $user,
'timecorrection' );
1095 $userTimeCorrection,
1100 if ( $userTimeCorrectionObj->getCorrectionType() === UserTimeCorrection::OFFSET ) {
1101 $tzDefault = UserTimeCorrection::formatTimezoneOffset( $userTimeCorrectionObj->getTimeOffset() );
1103 $tzDefault = $userTimeCorrectionObj->toString();
1106 $defaultPreferences[
'timecorrection'] = [
1107 'type' =>
'timezone',
1108 'label-message' =>
'timezonelegend',
1109 'default' => $tzDefault,
1111 'section' =>
'rendering/timeoffset',
1112 'id' =>
'wpTimeCorrection',
1113 'filter' => TimezoneFilter::class,
1125 &$defaultPreferences
1128 $defaultPreferences[
'diffonly'] = [
1130 'section' =>
'rendering/diffs',
1131 'label-message' =>
'tog-diffonly',
1133 $defaultPreferences[
'norollbackdiff'] = [
1135 'section' =>
'rendering/diffs',
1136 'label-message' =>
'tog-norollbackdiff',
1138 $defaultPreferences[
'diff-type'] = [
1144 $defaultPreferences[
'underline'] = [
1147 $l10n->
msg(
'underline-never' )->text() => 0,
1148 $l10n->
msg(
'underline-always' )->text() => 1,
1149 $l10n->
msg(
'underline-default' )->text() => 2,
1151 'label-message' =>
'tog-underline',
1152 'section' =>
'rendering/advancedrendering',
1156 $defaultPreferences[
'showhiddencats'] = [
1158 'section' =>
'rendering/advancedrendering',
1159 'label-message' =>
'tog-showhiddencats'
1163 $defaultPreferences[
'showrollbackconfirmation'] = [
1165 'section' =>
'rendering/advancedrendering',
1166 'label-message' =>
'tog-showrollbackconfirmation',
1170 $defaultPreferences[
'forcesafemode'] = [
1172 'section' =>
'rendering/advancedrendering',
1173 'label-message' =>
'tog-forcesafemode',
1174 'help-message' =>
'prefs-help-forcesafemode'
1184 $defaultPreferences[
'editsectiononrightclick'] = [
1186 'section' =>
'editing/advancedediting',
1187 'label-message' =>
'tog-editsectiononrightclick',
1189 $defaultPreferences[
'editondblclick'] = [
1191 'section' =>
'editing/advancedediting',
1192 'label-message' =>
'tog-editondblclick',
1196 $defaultPreferences[
'editfont'] = [
1198 'section' =>
'editing/editor',
1199 'label-message' =>
'editfont-style',
1201 $l10n->
msg(
'editfont-monospace' )->text() =>
'monospace',
1202 $l10n->
msg(
'editfont-sansserif' )->text() =>
'sans-serif',
1203 $l10n->
msg(
'editfont-serif' )->text() =>
'serif',
1208 if ( $user->
isAllowed(
'minoredit' ) ) {
1209 $defaultPreferences[
'minordefault'] = [
1211 'section' =>
'editing/editor',
1212 'label-message' =>
'tog-minordefault',
1216 $defaultPreferences[
'forceeditsummary'] = [
1218 'section' =>
'editing/editor',
1219 'label-message' =>
'tog-forceeditsummary',
1224 $defaultPreferences[
'editrecovery'] = [
1226 'section' =>
'editing/editor',
1227 'label-message' =>
'tog-editrecovery',
1229 'tog-editrecovery-help',
1230 'https://meta.wikimedia.org/wiki/Talk:Community_Wishlist_Survey_2023/Edit-recovery_feature',
1235 $defaultPreferences[
'useeditwarning'] = [
1237 'section' =>
'editing/editor',
1238 'label-message' =>
'tog-useeditwarning',
1241 $defaultPreferences[
'previewonfirst'] = [
1243 'section' =>
'editing/preview',
1244 'label-message' =>
'tog-previewonfirst',
1246 $defaultPreferences[
'previewontop'] = [
1248 'section' =>
'editing/preview',
1249 'label-message' =>
'tog-previewontop',
1251 $defaultPreferences[
'uselivepreview'] = [
1253 'section' =>
'editing/preview',
1254 'label-message' =>
'tog-uselivepreview',
1265 $rcMax = ceil( $rcMaxAge / ( 3600 * 24 ) );
1266 $defaultPreferences[
'rcdays'] = [
1268 'label-message' =>
'recentchangesdays',
1269 'section' =>
'rc/displayrc',
1274 $defaultPreferences[
'rclimit'] = [
1278 'label-message' =>
'recentchangescount',
1279 'help-message' =>
'prefs-help-recentchangescount',
1280 'section' =>
'rc/displayrc',
1281 'filter' => IntvalFilter::class,
1283 $defaultPreferences[
'usenewrc'] = [
1285 'label-message' =>
'tog-usenewrc',
1286 'section' =>
'rc/advancedrc',
1288 $defaultPreferences[
'hideminor'] = [
1290 'label-message' =>
'tog-hideminor',
1291 'section' =>
'rc/changesrc',
1293 $defaultPreferences[
'pst-cssjs'] = [
1296 $defaultPreferences[
'rcfilters-rc-collapsed'] = [
1299 $defaultPreferences[
'rcfilters-wl-collapsed'] = [
1302 $defaultPreferences[
'rcfilters-saved-queries'] = [
1305 $defaultPreferences[
'rcfilters-wl-saved-queries'] = [
1309 $defaultPreferences[
'rcfilters-limit'] = [
1312 $defaultPreferences[
'rcfilters-saved-queries-versionbackup'] = [
1315 $defaultPreferences[
'rcfilters-wl-saved-queries-versionbackup'] = [
1320 $defaultPreferences[
'hidecategorization'] = [
1322 'label-message' =>
'tog-hidecategorization',
1323 'section' =>
'rc/changesrc',
1328 $defaultPreferences[
'hidepatrolled'] = [
1330 'section' =>
'rc/changesrc',
1331 'label-message' =>
'tog-hidepatrolled',
1336 $defaultPreferences[
'newpageshidepatrolled'] = [
1338 'section' =>
'rc/changesrc',
1339 'label-message' =>
'tog-newpageshidepatrolled',
1344 $defaultPreferences[
'shownumberswatching'] = [
1346 'section' =>
'rc/advancedrc',
1347 'label-message' =>
'tog-shownumberswatching',
1351 $defaultPreferences[
'rcenhancedfilters-disable'] = [
1353 'section' =>
'rc/advancedrc',
1354 'label-message' =>
'rcfilters-preference-label',
1355 'help-message' =>
'rcfilters-preference-help',
1369 if ( $user->
isAllowed(
'editmywatchlist' ) ) {
1370 $editWatchlistLinks =
'';
1371 $editWatchlistModes = [
1372 'edit' => [
'subpage' =>
false,
'flags' => [] ],
1373 'raw' => [
'subpage' =>
'raw',
'flags' => [] ],
1374 'clear' => [
'subpage' =>
'clear',
'flags' => [
'destructive' ] ],
1376 foreach ( $editWatchlistModes as $mode =>
$options ) {
1378 $editWatchlistLinks .=
1382 'label' =>
new HtmlSnippet(
1383 $context->
msg(
"prefs-editwatchlist-{$mode}" )->parse()
1388 $defaultPreferences[
'editwatchlist'] = [
1391 'default' => $editWatchlistLinks,
1392 'label-message' =>
'prefs-editwatchlist-label',
1393 'section' =>
'watchlist/editwatchlist',
1397 $defaultPreferences[
'watchlistdays'] = [
1400 'max' => $watchlistdaysMax,
1401 'section' =>
'watchlist/displaywatchlist',
1402 'help-message' => [
'prefs-watchlist-days-max',
Message::numParam( $watchlistdaysMax ) ],
1403 'label-message' =>
'prefs-watchlist-days',
1405 $defaultPreferences[
'wllimit'] = [
1409 'label-message' =>
'prefs-watchlist-edits',
1410 'help-message' =>
'prefs-watchlist-edits-max',
1411 'section' =>
'watchlist/displaywatchlist',
1412 'filter' => IntvalFilter::class,
1414 $defaultPreferences[
'extendwatchlist'] = [
1416 'section' =>
'watchlist/advancedwatchlist',
1417 'label-message' =>
'tog-extendwatchlist',
1419 $defaultPreferences[
'watchlisthideminor'] = [
1421 'section' =>
'watchlist/changeswatchlist',
1422 'label-message' =>
'tog-watchlisthideminor',
1424 $defaultPreferences[
'watchlisthidebots'] = [
1426 'section' =>
'watchlist/changeswatchlist',
1427 'label-message' =>
'tog-watchlisthidebots',
1429 $defaultPreferences[
'watchlisthideown'] = [
1431 'section' =>
'watchlist/changeswatchlist',
1432 'label-message' =>
'tog-watchlisthideown',
1434 $defaultPreferences[
'watchlisthideanons'] = [
1436 'section' =>
'watchlist/changeswatchlist',
1437 'label-message' =>
'tog-watchlisthideanons',
1439 $defaultPreferences[
'watchlisthideliu'] = [
1441 'section' =>
'watchlist/changeswatchlist',
1442 'label-message' =>
'tog-watchlisthideliu',
1446 $defaultPreferences[
'watchlistreloadautomatically'] = [
1448 'section' =>
'watchlist/advancedwatchlist',
1449 'label-message' =>
'tog-watchlistreloadautomatically',
1453 $defaultPreferences[
'watchlistunwatchlinks'] = [
1455 'section' =>
'watchlist/advancedwatchlist',
1456 'label-message' =>
'tog-watchlistunwatchlinks',
1460 $defaultPreferences[
'watchlisthidecategorization'] = [
1462 'section' =>
'watchlist/changeswatchlist',
1463 'label-message' =>
'tog-watchlisthidecategorization',
1468 $defaultPreferences[
'watchlisthidepatrolled'] = [
1470 'section' =>
'watchlist/changeswatchlist',
1471 'label-message' =>
'tog-watchlisthidepatrolled',
1476 'edit' =>
'watchdefault',
1477 'move' =>
'watchmoves',
1481 if ( $user->
isAllowedAny(
'createpage',
'createtalk' ) ) {
1482 $watchTypes[
'read'] =
'watchcreations';
1487 'rollback' =>
'watchrollback',
1488 'upload' =>
'watchuploads',
1489 'delete' =>
'watchdeletion',
1492 foreach ( $watchTypes as $action => $pref ) {
1497 $defaultPreferences[$pref] = [
1499 'section' =>
'watchlist/pageswatchlist',
1500 'label-message' =>
"tog-$pref",
1505 $defaultPreferences[
'watchlisttoken'] = [
1509 $tokenButton =
new ButtonWidget( [
1513 'label' => $context->
msg(
'prefs-watchlist-managetokens' )->text(),
1515 $defaultPreferences[
'watchlisttoken-info'] = [
1517 'section' =>
'watchlist/tokenwatchlist',
1518 'label-message' =>
'prefs-watchlist-token',
1519 'help-message' =>
'prefs-help-tokenmanagement',
1521 'default' => (string)$tokenButton,
1524 $defaultPreferences[
'wlenhancedfilters-disable'] = [
1526 'section' =>
'watchlist/advancedwatchlist',
1527 'label-message' =>
'rcfilters-watchlist-preference-label',
1528 'help-message' =>
'rcfilters-watchlist-preference-help',
1537 $defaultPreferences[
'search-special-page'] = [
1541 foreach ( $this->nsInfo->getValidNamespaces() as $n ) {
1542 $defaultPreferences[
'searchNs' . $n] = [
1548 $defaultPreferences[
'search-match-redirect'] = [
1550 'section' =>
'searchoptions/searchmisc',
1551 'label-message' =>
'search-match-redirect-label',
1552 'help-message' =>
'search-match-redirect-help',
1555 $defaultPreferences[
'search-match-redirect'] = [
1560 $defaultPreferences[
'searchlimit'] = [
1564 'section' =>
'searchoptions/searchmisc',
1565 'label-message' =>
'searchlimit-label',
1566 'help-message' => $context->
msg(
'searchlimit-help', 500 ),
1567 'filter' => IntvalFilter::class,
1573 $thumbNamespacesFormatted = array_combine(
1576 static function ( $namespaceId ) use ( $context ) {
1577 return $namespaceId ===
NS_MAIN
1578 ? $context->
msg(
'blanknamespace' )->escaped()
1579 : $context->
getLanguage()->getFormattedNsText( $namespaceId );
1584 $defaultThumbNamespacesFormatted =
1585 array_intersect_key( $thumbNamespacesFormatted, [
NS_FILE => 1 ] ) ?? [];
1586 $extraThumbNamespacesFormatted =
1587 array_diff_key( $thumbNamespacesFormatted, [
NS_FILE => 1 ] );
1588 if ( $extraThumbNamespacesFormatted ) {
1589 $defaultPreferences[
'search-thumbnail-extra-namespaces'] = [
1591 'section' =>
'searchoptions/searchmisc',
1592 'label-message' =>
'search-thumbnail-extra-namespaces-label',
1593 'help-message' => $context->
msg(
1594 'search-thumbnail-extra-namespaces-message',
1595 $context->
getLanguage()->listToText( $extraThumbNamespacesFormatted ),
1596 count( $extraThumbNamespacesFormatted ),
1597 $context->
getLanguage()->listToText( $defaultThumbNamespacesFormatted ),
1598 count( $defaultThumbNamespacesFormatted )
1613 private static function sortSkinNames( $a, $b, $currentSkin, $preferredSkins ) {
1615 if ( strcasecmp( $a, $currentSkin ) === 0 ) {
1618 if ( strcasecmp( $b, $currentSkin ) === 0 ) {
1622 if ( count( $preferredSkins ) ) {
1623 $aPreferred = array_search( $a, $preferredSkins );
1624 $bPreferred = array_search( $b, $preferredSkins );
1627 if ( $aPreferred !==
false && $bPreferred ===
false ) {
1630 if ( $aPreferred ===
false && $bPreferred !==
false ) {
1635 if ( $aPreferred !==
false && $bPreferred !==
false ) {
1636 return strcasecmp( $aPreferred, $bPreferred );
1640 return strcasecmp( $a, $b );
1651 private function getValidSkinNames( User $user, IContextSource $context ) {
1653 $validSkinNames = $this->skinFactory->getAllowedSkins();
1654 $allInstalledSkins = $this->skinFactory->getInstalledSkins();
1657 $useSkin = $context->getRequest()->getRawVal(
'useskin' );
1658 if ( isset( $allInstalledSkins[$useSkin] )
1659 && $context->msg(
"skinname-$useSkin" )->exists()
1661 $validSkinNames[$useSkin] = $useSkin;
1665 $currentUserSkin = $this->userOptionsManager->getOption( $user,
'skin' );
1666 if ( isset( $allInstalledSkins[$currentUserSkin] )
1667 && $context->msg(
"skinname-$currentUserSkin" )->exists()
1669 $validSkinNames[$currentUserSkin] = $currentUserSkin;
1672 foreach ( $validSkinNames as $skinkey => &$skinname ) {
1673 $msg = $context->msg(
"skinname-{$skinkey}" );
1674 if ( $msg->exists() ) {
1675 $skinname = htmlspecialchars( $msg->text() );
1682 uksort( $validSkinNames,
function ( $a, $b ) use ( $currentUserSkin, $preferredSkins ) {
1683 return $this->sortSkinNames( $a, $b, $currentUserSkin, $preferredSkins );
1686 return $validSkinNames;
1698 $mptitle = Title::newMainPage();
1699 $previewtext = $context->
msg(
'skin-preview' )->escaped();
1703 $safeMode = $this->userOptionsManager->getOption( $user,
'forcesafemode' );
1704 $foundDefault =
false;
1705 foreach ( $validSkinNames as $skinkey => $sn ) {
1709 if ( strcasecmp( $skinkey, $defaultSkin ) === 0 ) {
1710 $linkTools[] = $context->
msg(
'default' )->escaped();
1711 $foundDefault =
true;
1715 $talkPageMsg = $context->
msg(
"$skinkey-prefs-talkpage" );
1716 if ( $talkPageMsg->exists() ) {
1717 $linkTools[] = $talkPageMsg->parse();
1721 $mplink = htmlspecialchars( $mptitle->getLocalURL( [
'useskin' => $skinkey ] ) );
1722 $linkTools[] =
"<a target='_blank' href=\"$mplink\">$previewtext</a>";
1727 if ( $allowUserCss ) {
1728 $cssPage = Title::makeTitleSafe(
NS_USER, $user->
getName() .
'/' . $skinkey .
'.css' );
1729 $cssLinkText = $context->
msg(
'prefs-custom-css' )->text();
1730 $linkTools[] = $this->linkRenderer->makeLink( $cssPage, $cssLinkText );
1733 if ( $allowUserJs ) {
1734 $jsPage = Title::makeTitleSafe(
NS_USER, $user->
getName() .
'/' . $skinkey .
'.js' );
1735 $jsLinkText = $context->
msg(
'prefs-custom-js' )->text();
1736 $linkTools[] = $this->linkRenderer->makeLink( $jsPage, $jsLinkText );
1740 $display = $sn .
' ' . $context->
msg(
'parentheses' )
1741 ->rawParams( $context->
getLanguage()->pipeList( $linkTools ) )
1743 $ret[$display] = $skinkey;
1746 if ( !$foundDefault ) {
1761 $dateopts = $lang->getDatePreferences();
1766 if ( !in_array(
'default', $dateopts ) ) {
1767 $dateopts[] =
'default';
1777 foreach ( $dateopts as $key ) {
1778 if ( $key ==
'default' ) {
1779 $formatted = $context->
msg(
'datedefault' )->escaped();
1781 $formatted = htmlspecialchars( $lang->timeanddate( $epoch,
false, $key ) );
1783 $ret[$formatted] = $key;
1795 $pixels = $l10n->
msg(
'unit-pixel' )->text();
1799 $display =
"{$limits[0]}\u{200E}×{$limits[1]}$pixels";
1800 $ret[$display] = $index;
1812 $pixels = $l10n->
msg(
'unit-pixel' )->text();
1815 $display = $size . $pixels;
1816 $ret[$display] = $index;
1831 if ( is_string( $signature ) && mb_strlen( $signature ) > $maxSigChars ) {
1832 return $form->
msg(
'badsiglength' )->numParams( $maxSigChars )->escaped();
1835 if ( $signature ===
null || $signature ===
'' ) {
1842 if ( !( isset( $alldata[
'fancysig'] ) && $alldata[
'fancysig'] ) ) {
1859 $signature === $this->userOptionsManager->getOption( $user,
'nickname' ) &&
1860 (
bool)$alldata[
'fancysig'] === $this->userOptionsManager->getBoolOption( $user,
'fancysig' )
1865 if ( $sigValidation ===
'new' || $sigValidation ===
'disallow' ) {
1867 $parserOpts = ParserOptions::newFromContext( $form->
getContext() );
1868 $validator = $this->signatureValidatorFactory
1869 ->newSignatureValidator( $user, $form->
getContext(), $parserOpts );
1870 $errors = $validator->validateSignature( $signature );
1879 if ( $this->parserFactory->getInstance()->validateSig( $signature ) ===
false ) {
1880 return $form->
msg(
'badsig' )->escaped();
1893 if ( isset( $alldata[
'fancysig'] ) && $alldata[
'fancysig'] ) {
1894 $signature = $this->parserFactory->getInstance()->cleanSig( $signature );
1897 $signature = Parser::cleanSigInSig( $signature );
1913 $formClass = PreferencesFormOOUI::class,
1921 if ( count( $remove ) ) {
1922 $removeKeys = array_fill_keys( $remove,
true );
1923 $formDescriptor = array_diff_key( $formDescriptor, $removeKeys );
1927 foreach ( $formDescriptor as $name => $info ) {
1928 if ( isset( $info[
'type'] ) && $info[
'type'] ===
'api' ) {
1929 unset( $formDescriptor[$name] );
1936 $htmlForm =
new $formClass( $formDescriptor, $context,
'prefs' );
1942 $htmlForm->setAction( $context->
getTitle()->getLocalURL( [
1943 'useskin' => $context->
getRequest()->getRawVal(
'useskin' )
1946 $htmlForm->setModifiedUser( $user );
1947 $htmlForm->setOptionsEditable( $user->
isAllowed(
'editmyoptions' ) );
1948 $htmlForm->setPrivateInfoEditable( $user->
isAllowed(
'editmyprivateinfo' ) );
1949 $htmlForm->setId(
'mw-prefs-form' );
1950 $htmlForm->setAutocomplete(
'off' );
1951 $htmlForm->setSubmitTextMsg(
'saveprefs' );
1953 $htmlForm->setSubmitTooltip(
'preferences-save' );
1954 $htmlForm->setSubmitID(
'prefcontrol' );
1955 $htmlForm->setSubmitCallback(
1957 return $this->
submitForm( $formData, $form, $formDescriptor );
1977 if ( !$user->isAllowedAny(
'editmyprivateinfo',
'editmyoptions' ) ) {
1978 return Status::newFatal(
'mypreferencesprotected' );
1982 $this->
applyFilters( $formData, $formDescriptor,
'filterFromForm' );
1987 if ( !in_array(
'realname', $hiddenPrefs )
1988 && $user->isAllowed(
'editmyprivateinfo' )
1989 && array_key_exists(
'realname', $formData )
1991 $realName = $formData[
'realname'];
1992 $user->setRealName( $realName );
1995 if ( $user->isAllowed(
'editmyoptions' ) ) {
1996 $oldUserOptions = $this->userOptionsManager->getOptions( $user );
1999 unset( $formData[$b] );
2005 foreach ( $hiddenPrefs as $pref ) {
2008 $formData[$pref] = $this->userOptionsManager->getOption( $user, $pref,
null,
true );
2013 isset( $formData[
'rclimit'] ) &&
2014 intval( $formData[
'rclimit' ] ) !== $this->userOptionsManager->getIntOption( $user,
'rclimit' )
2016 $formData[
'rcfilters-limit'] = $formData[
'rclimit'];
2021 $this->userOptionsManager->resetOptionsByName( $user, $optionsToReset );
2023 foreach ( $formData as $key => $value ) {
2027 $except = !empty( $formData[$key . UserOptionsLookup::LOCAL_EXCEPTION_SUFFIX] );
2028 $this->userOptionsManager->setOption( $user, $key, $value,
2029 $except ? UserOptionsManager::GLOBAL_OVERRIDE : UserOptionsManager::GLOBAL_IGNORE );
2032 $this->hookRunner->onPreferencesFormPreSave(
2033 $formData, $form, $user, $result, $oldUserOptions );
2036 $user->saveSettings();
2049 protected function applyFilters( array &$preferences, array $formDescriptor, $verb ) {
2050 foreach ( $formDescriptor as $preference => $desc ) {
2051 if ( !isset( $desc[
'filter'] ) || !isset( $preferences[$preference] ) ) {
2054 $filterDesc = $desc[
'filter'];
2055 if ( $filterDesc instanceof
Filter ) {
2056 $filter = $filterDesc;
2057 } elseif ( class_exists( $filterDesc ) ) {
2058 $filter =
new $filterDesc();
2059 } elseif ( is_callable( $filterDesc ) ) {
2060 $filter = $filterDesc();
2062 throw new UnexpectedValueException(
2063 "Unrecognized filter type for preference '$preference'"
2066 $preferences[$preference] = $filter->$verb( $preferences[$preference] );
2081 array $formDescriptor
2083 $res = $this->
saveFormData( $formData, $form, $formDescriptor );
2085 if ( $res ===
true ) {
2094 $context->getRequest()->getSession()->set(
'specialPreferencesSaveSuccess', 1 );
2096 $context->getOutput()->redirect(
$url );
2099 return ( $res ===
true ? Status::newGood() : $res );
2106 $options = $this->userOptionsManager->loadUserOptions( $user );
2115 foreach ( $specialOptions as $name => $value ) {
2116 unset( $prefs[$name] );
2121 $multiselectOptions = [];
2122 foreach ( $prefs as $name => $info ) {
2123 if ( ( isset( $info[
'type'] ) && $info[
'type'] ==
'multiselect' ) ||
2125 ( isset( $info[
'class'] ) && $info[
'class'] === \HTMLMultiSelectField::class ) ||
2126 ( isset( $info[
'class'] ) && $info[
'class'] === HTMLMultiSelectField::class )
2128 $opts = HTMLFormField::flattenOptions( $info[
'options'] ?? $info[
'options-messages'] );
2129 $prefix = $info[
'prefix'] ?? $name;
2131 foreach ( $opts as $value ) {
2132 $multiselectOptions[
"$prefix$value"] =
true;
2135 unset( $prefs[$name] );
2138 $checkmatrixOptions = [];
2139 foreach ( $prefs as $name => $info ) {
2140 if ( ( isset( $info[
'type'] ) && $info[
'type'] ==
'checkmatrix' ) ||
2142 ( isset( $info[
'class'] ) && $info[
'class'] === \HTMLCheckMatrix::class ) ||
2143 ( isset( $info[
'class'] ) && $info[
'class'] === HTMLCheckMatrix::class )
2145 $columns = HTMLFormField::flattenOptions( $info[
'columns'] );
2146 $rows = HTMLFormField::flattenOptions( $info[
'rows'] );
2147 $prefix = $info[
'prefix'] ?? $name;
2149 foreach ( $columns as $column ) {
2150 foreach ( $rows as $row ) {
2151 $checkmatrixOptions[
"$prefix$column-$row"] =
true;
2155 unset( $prefs[$name] );
2160 foreach (
$options as $key => $value ) {
2161 if ( isset( $prefs[$key] ) ) {
2162 $mapping[$key] =
'registered';
2163 } elseif ( isset( $multiselectOptions[$key] ) ) {
2164 $mapping[$key] =
'registered-multiselect';
2165 } elseif ( isset( $checkmatrixOptions[$key] ) ) {
2166 $mapping[$key] =
'registered-checkmatrix';
2167 } elseif ( isset( $specialOptions[$key] ) ) {
2168 $mapping[$key] =
'special';
2169 } elseif ( str_starts_with( $key,
'userjs-' ) ) {
2170 $mapping[$key] =
'userjs';
2171 } elseif ( str_starts_with( $key, UserOptionsLookup::LOCAL_EXCEPTION_SUFFIX ) ) {
2172 $mapping[$key] =
'local-exception';
2174 $mapping[$key] =
'unused';
2184 'registered-multiselect',
2185 'registered-checkmatrix',
2193 $oldOptions = $this->userOptionsManager->loadUserOptions( $user, IDBAccessObject::READ_LATEST );
2195 if ( !is_array( $kinds ) ) {
2196 $kinds = [ $kinds ];
2199 if ( in_array(
'all', $kinds ) ) {
2200 return array_keys( $oldOptions );
2202 $optionKinds = $this->getResetKinds( $user, $context );
2203 $kinds = array_intersect( $kinds, $this->listResetKinds() );
2206 foreach ( $oldOptions as $key => $value ) {
2207 if ( in_array( $optionKinds[$key], $kinds ) ) {
2208 $optionNames[] = $key;
2211 return $optionNames;
wfTimestampNow()
Convenience function; returns MediaWiki timestamp for the present time.
array $params
The job parameters.
if(!defined('MW_SETUP_CALLBACK'))
Methods for dealing with language codes.
Base class for multi-variant language conversion.
Base class for language-specific code.
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 AllowRequiringEmailForResets
Name constant for the AllowRequiringEmailForResets 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,...
Set options of the Parser.
Factory class to create Skin objects.
$wgDefaultUserOptions
Config variable stub for the DefaultUserOptions setting, for use by phpdoc and IDEs.
Interface for database access objects.
The shared interface for all language converters.
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.