57use Psr\Log\LoggerAwareTrait;
58use Psr\Log\NullLogger;
63use UnexpectedValueException;
66use Wikimedia\RequestTimeout\TimeoutException;
97 private $languageConverter;
103 private $userOptionsManager;
106 private $languageConverterFactory;
112 private $skinFactory;
115 private $userGroupManager;
118 private $signatureValidatorFactory;
201 $this->logger =
new NullLogger();
202 $this->languageConverter = $languageConverter;
204 $this->hookRunner =
new HookRunner( $hookContainer );
208 $services =
static function () {
214 : $services()->getUserOptionsManager();
215 $this->languageConverterFactory = $languageConverterFactory ?? $services()->getLanguageConverterFactory();
217 $this->parser = $parser ?? $services()->getParser();
218 $this->skinFactory = $skinFactory ?? $services()->getSkinFactory();
219 $this->userGroupManager = $userGroupManager ?? $services()->getUserGroupManager();
220 $this->signatureValidatorFactory = $signatureValidatorFactory
221 ?? $services()->getSignatureValidatorFactory();
243 OutputPage::setupOOUI(
244 strtolower( $context->
getSkin()->getSkinName() ),
258 $this->hookRunner->onGetPreferences( $user, $preferences );
260 $this->loadPreferenceValues( $user, $context, $preferences );
261 $this->logger->debug(
"Created form descriptor for user '{$user->getName()}'" );
272 foreach ( $descriptor as $name => &$params ) {
275 if ( ( isset( $params[
'type'] ) && $params[
'type'] ===
'info' ) ||
276 ( isset( $params[
'class'] ) && $params[
'class'] === \HTMLInfoField::class )
278 unset( $descriptor[$name] );
283 foreach ( $params as $key => $value ) {
286 case 'options-message':
289 case 'options-messages':
290 unset( $params[$key] );
291 $params[
'options'] = $value;
294 if ( preg_match(
'/-messages?$/', $key ) ) {
296 unset( $params[$key] );
312 private function loadPreferenceValues(
User $user,
IContextSource $context, &$defaultPreferences ) {
315 unset( $defaultPreferences[$pref] );
320 $form =
new HTMLForm( $simplified, $context );
322 $disable = !$user->
isAllowed(
'editmyoptions' );
324 $defaultOptions = $this->userOptionsManager->getDefaultOptions();
325 $userOptions = $this->userOptionsManager->getOptions( $user );
326 $this->
applyFilters( $userOptions, $defaultPreferences,
'filterForForm' );
328 foreach ( $simplified as $name => $_ ) {
329 $info = &$defaultPreferences[$name];
331 $info[
'disabled'] =
'disabled';
333 if ( isset( $info[
'default'] ) ) {
337 $field = $form->getField( $name );
338 $globalDefault = $defaultOptions[$name] ??
null;
344 if ( $prefFromUser !==
null &&
345 $field->validate( $prefFromUser, $this->userOptionsManager->getOptions( $user ) ) ===
true ) {
346 $info[
'default'] = $prefFromUser;
347 } elseif ( $field->validate( $globalDefault, $this->userOptionsManager->getOptions( $user ) ) ===
true ) {
348 $info[
'default'] = $globalDefault;
350 $globalDefault = json_encode( $globalDefault );
352 "Default '$globalDefault' is invalid for preference $name of user " . $user->
getName()
357 return $defaultPreferences;
369 $val = $userOptions[$name] ??
null;
372 if ( ( isset( $info[
'type'] ) && $info[
'type'] ==
'multiselect' ) ||
373 ( isset( $info[
'class'] ) && $info[
'class'] == \HTMLMultiSelectField::class ) ) {
374 $options = HTMLFormField::flattenOptions( $info[
'options-messages'] ?? $info[
'options'] );
375 $prefix = $info[
'prefix'] ?? $name;
379 if ( $userOptions[
"$prefix$value"] ??
false ) {
386 if ( ( isset( $info[
'type'] ) && $info[
'type'] ==
'checkmatrix' ) ||
387 ( isset( $info[
'class'] ) && $info[
'class'] == \HTMLCheckMatrix::class ) ) {
388 $columns = HTMLFormField::flattenOptions( $info[
'columns'] );
389 $rows = HTMLFormField::flattenOptions( $info[
'rows'] );
390 $prefix = $info[
'prefix'] ?? $name;
393 foreach ( $columns as $column ) {
394 foreach ( $rows as $row ) {
395 if ( $userOptions[
"$prefix$column-$row"] ??
false ) {
396 $val[] =
"$column-$row";
419 $defaultPreferences[
'username'] = [
421 'label-message' => [
'username', $userName ],
422 'default' => $userName,
423 'section' =>
'personal/info',
429 $userEffectiveGroups = array_diff(
430 $this->userGroupManager->getUserEffectiveGroups( $user ),
433 $defaultPreferences[
'usergroups'] = [
435 'label-message' => [
'prefs-memberingroups',
436 \Message::numParam( count( $userEffectiveGroups ) ), $userName ],
437 'default' =>
function () use ( $user, $userEffectiveGroups, $context,
$lang, $userName ) {
438 $userGroupMemberships = $this->userGroupManager->getUserGroupMemberships( $user );
439 $userGroups = $userMembers = $userTempGroups = $userTempMembers = [];
440 foreach ( $userEffectiveGroups as $ueg ) {
441 $groupStringOrObject = $userGroupMemberships[$ueg] ?? $ueg;
443 $userG = UserGroupMembership::getLink( $groupStringOrObject, $context,
'html' );
444 $userM = UserGroupMembership::getLink( $groupStringOrObject, $context,
'html',
454 $userTempGroups[] = $userG;
455 $userTempMembers[] = $userM;
457 $userGroups[] = $userG;
458 $userMembers[] = $userM;
462 sort( $userMembers );
463 sort( $userTempGroups );
464 sort( $userTempMembers );
465 $userGroups = array_merge( $userTempGroups, $userGroups );
466 $userMembers = array_merge( $userTempMembers, $userMembers );
467 return $context->
msg(
'prefs-memberingroups-type' )
468 ->rawParams(
$lang->commaList( $userGroups ),
$lang->commaList( $userMembers ) )
472 'section' =>
'personal/info',
477 $editCount = $this->linkRenderer->makeLink( $contribTitle, $formattedEditCount );
479 $defaultPreferences[
'editcount'] = [
482 'label-message' =>
'prefs-edits',
483 'default' => $editCount,
484 'section' =>
'personal/info',
488 $displayUser = $context->
getUser();
490 $defaultPreferences[
'registrationdate'] = [
492 'label-message' =>
'prefs-registration',
493 'default' => $context->
msg(
494 'prefs-registration-date-time',
495 $lang->userTimeAndDate( $userRegistration, $displayUser ),
496 $lang->userDate( $userRegistration, $displayUser ),
497 $lang->userTime( $userRegistration, $displayUser )
499 'section' =>
'personal/info',
503 $canViewPrivateInfo = $user->
isAllowed(
'viewmyprivateinfo' );
504 $canEditPrivateInfo = $user->
isAllowed(
'editmyprivateinfo' );
507 $defaultPreferences[
'realname'] = [
509 'type' => $canEditPrivateInfo && $this->authManager->allowsPropertyChange(
'realname' )
512 'section' =>
'personal/info',
513 'label-message' =>
'yourrealname',
514 'help-message' =>
'prefs-help-realname',
517 if ( $canEditPrivateInfo && $this->authManager->allowsAuthenticationDataChange(
520 $defaultPreferences[
'password'] = [
523 'default' => (string)
new \OOUI\ButtonWidget( [
527 'label' => $context->
msg(
'prefs-resetpass' )->text(),
529 'label-message' =>
'yourpassword',
533 ? $context->
msg(
'prefs-help-yourpassword',
534 '[[#mw-prefsection-personal-email|{{int:prefs-email}}]]' )->parse()
536 'section' =>
'personal/info',
543 $defaultPreferences[
'prefershttps'] = [
545 'label-message' =>
'tog-prefershttps',
546 'help-message' =>
'prefs-help-prefershttps',
547 'section' =>
'personal/info'
551 $defaultPreferences[
'downloaduserdata'] = [
554 'label-message' =>
'prefs-user-downloaddata-label',
555 'default' => Html::element(
559 '/api.php?action=query&meta=userinfo&uiprop=*',
561 $context->
msg(
'prefs-user-downloaddata-info' )->text()
563 'help-message' => [
'prefs-user-downloaddata-help-message', urlencode( $user->
getTitleKey() ) ],
564 'section' =>
'personal/info',
567 $defaultPreferences[
'restoreprefs'] = [
570 'label-message' =>
'prefs-user-restoreprefs-label',
571 'default' => Html::element(
575 ->getSubpage(
'reset' )->getLocalURL()
577 $context->
msg(
'prefs-user-restoreprefs-info' )->text()
579 'section' =>
'personal/info',
582 $languages = $this->languageNameUtils->getLanguageNames(
583 LanguageNameUtils::AUTONYMS,
584 LanguageNameUtils::SUPPORTED
587 if ( !array_key_exists( $languageCode, $languages ) ) {
588 $languages[$languageCode] = $languageCode;
594 foreach ( $languages as $code => $name ) {
595 $display = LanguageCode::bcp47( $code ) .
' - ' . $name;
598 $defaultPreferences[
'language'] = [
600 'section' =>
'personal/i18n',
602 'label-message' =>
'yourlanguage',
605 $neutralGenderMessage = $context->
msg(
'gender-notknown' )->escaped() . (
606 !$context->
msg(
'gender-unknown' )->isDisabled()
607 ?
"<br>" . $context->
msg(
'parentheses' )
608 ->params( $context->
msg(
'gender-unknown' )->plain() )
613 $defaultPreferences[
'gender'] = [
615 'section' =>
'personal/i18n',
617 $neutralGenderMessage =>
'unknown',
618 $context->
msg(
'gender-female' )->escaped() =>
'female',
619 $context->
msg(
'gender-male' )->escaped() =>
'male',
621 'label-message' =>
'yourgender',
622 'help-message' =>
'prefs-help-gender',
626 if ( !$this->languageConverterFactory->isConversionDisabled() ) {
628 foreach ( LanguageConverter::$languagesWithVariants as $langCode ) {
629 if ( $langCode == $this->contLang->getCode() ) {
630 if ( !$this->languageConverter->hasVariants() ) {
634 $variants = $this->languageConverter->getVariants();
636 foreach ( $variants as $v ) {
637 $v = str_replace(
'_',
'-', strtolower( $v ) );
638 $variantArray[$v] =
$lang->getVariantname( $v,
false );
642 foreach ( $variantArray as $code => $name ) {
643 $display = LanguageCode::bcp47( $code ) .
' - ' . $name;
647 $defaultPreferences[
'variant'] = [
648 'label-message' =>
'yourvariant',
651 'section' =>
'personal/i18n',
652 'help-message' =>
'prefs-help-variant',
655 $defaultPreferences[
"variant-$langCode"] = [
663 $oldsigWikiText = $this->parser->preSaveTransform(
667 ParserOptions::newFromContext( $context )
670 $context->
getOutput()->parseAsContent( $oldsigWikiText )
672 $signatureFieldConfig = [];
674 $signature = $this->userOptionsManager->getOption( $user,
'nickname' );
675 $useFancySig = $this->userOptionsManager->getBoolOption( $user,
'fancysig' );
676 if ( $useFancySig && $signature !==
'' ) {
677 $parserOpts = ParserOptions::newFromContext( $context );
678 $validator = $this->signatureValidatorFactory
679 ->newSignatureValidator( $user, $context, $parserOpts );
680 $signatureErrors = $validator->validateSignature( $signature );
681 if ( $signatureErrors ) {
683 $oldsigHTML .=
'<p><strong>' .
688 $context->
msg(
"prefs-signature-invalid-$sigValidation" )->parse() .
693 foreach ( $signatureErrors as &$sigError ) {
694 $sigError = new \OOUI\HtmlSnippet( $sigError );
697 $signatureFieldConfig = [
698 'warnings' => $sigValidation !==
'disallow' ? $signatureErrors :
null,
699 'errors' => $sigValidation ===
'disallow' ? $signatureErrors :
null,
704 $defaultPreferences[
'oldsig'] = [
709 'default' => new \OOUI\FieldLayout(
710 new \OOUI\LabelWidget( [
711 'label' =>
new \OOUI\HtmlSnippet( $oldsigHTML ),
715 'label' =>
new \OOUI\HtmlSnippet( $context->
msg(
'tog-oldsig' )->parse() )
716 ] + $signatureFieldConfig
718 'section' =>
'personal/signature',
720 $defaultPreferences[
'nickname'] = [
721 'type' => $this->authManager->allowsPropertyChange(
'nickname' ) ?
'text' :
'info',
723 'label-message' =>
'yournick',
724 'validation-callback' =>
function ( $signature, $alldata,
HTMLForm $form ) {
727 'section' =>
'personal/signature',
728 'filter-callback' =>
function ( $signature, array $alldata,
HTMLForm $form ) {
732 $defaultPreferences[
'fancysig'] = [
734 'label-message' =>
'tog-fancysig',
736 'help-message' =>
'prefs-help-signature',
737 'section' =>
'personal/signature'
742 if ( $canViewPrivateInfo ) {
745 ?
'prefs-help-email-required'
746 :
'prefs-help-email';
750 $helpMessages[] =
'prefs-help-email-others';
753 $emailAddress = $user->
getEmail() ? htmlspecialchars( $user->
getEmail() ) :
'';
754 if ( $canEditPrivateInfo && $this->authManager->allowsPropertyChange(
'emailaddress' ) ) {
755 $button = new \OOUI\ButtonWidget( [
760 $context->
msg( $user->
getEmail() ?
'prefs-changeemail' :
'prefs-setemail' )->text(),
763 $emailAddress .= $emailAddress ==
'' ? $button : (
'<br />' . $button );
766 $defaultPreferences[
'emailaddress'] = [
769 'default' => $emailAddress,
770 'label-message' =>
'youremail',
771 'section' =>
'personal/email',
772 'help-messages' => $helpMessages,
777 $disableEmailPrefs =
false;
780 $defaultPreferences[
'requireemail'] = [
782 'label-message' =>
'tog-requireemail',
783 'help-message' =>
'prefs-help-requireemail',
784 'section' =>
'personal/email',
785 'disabled' => $user->
getEmail() ? false :
true,
795 $displayUser = $context->
getUser();
797 $time =
$lang->userTimeAndDate( $emailTimestamp, $displayUser );
798 $d =
$lang->userDate( $emailTimestamp, $displayUser );
799 $t =
$lang->userTime( $emailTimestamp, $displayUser );
800 $emailauthenticated = $context->
msg(
'emailauthenticated',
801 $time, $d,
$t )->parse() .
'<br />';
802 $emailauthenticationclass =
'mw-email-authenticated';
804 $disableEmailPrefs =
true;
805 $emailauthenticated = $context->
msg(
'emailnotauthenticated' )->parse() .
'<br />' .
806 new \OOUI\ButtonWidget( [
808 'label' => $context->
msg(
'emailconfirmlink' )->text(),
810 $emailauthenticationclass =
"mw-email-not-authenticated";
813 $disableEmailPrefs =
true;
814 $emailauthenticated = $context->
msg(
'noemailprefs' )->escaped();
815 $emailauthenticationclass =
'mw-email-none';
818 if ( $canViewPrivateInfo ) {
819 $defaultPreferences[
'emailauthentication'] = [
822 'section' =>
'personal/email',
823 'label-message' =>
'prefs-emailconfirm-label',
824 'default' => $emailauthenticated,
826 'cssclass' => $emailauthenticationclass,
834 $defaultPreferences[
'disablemail'] = [
835 'id' =>
'wpAllowEmail',
838 'section' =>
'personal/email',
839 'label-message' =>
'allowemail',
840 'disabled' => $disableEmailPrefs,
843 $defaultPreferences[
'email-allow-new-users'] = [
844 'id' =>
'wpAllowEmailFromNewUsers',
846 'section' =>
'personal/email',
847 'label-message' =>
'email-allow-new-users-label',
848 'disabled' => $disableEmailPrefs,
849 'disable-if' => [
'!==',
'disablemail',
'1' ],
852 $defaultPreferences[
'ccmeonemails'] = [
854 'section' =>
'personal/email',
855 'label-message' =>
'tog-ccmeonemails',
856 'disabled' => $disableEmailPrefs,
860 $defaultPreferences[
'email-blacklist'] = [
861 'type' =>
'usersmultiselect',
862 'label-message' =>
'email-mutelist-label',
863 'section' =>
'personal/email',
864 'disabled' => $disableEmailPrefs,
865 'filter' => MultiUsernameFilter::class,
871 $defaultPreferences[
'enotifwatchlistpages'] = [
873 'section' =>
'personal/email',
874 'label-message' =>
'tog-enotifwatchlistpages',
875 'disabled' => $disableEmailPrefs,
879 $defaultPreferences[
'enotifusertalkpages'] = [
881 'section' =>
'personal/email',
882 'label-message' =>
'tog-enotifusertalkpages',
883 'disabled' => $disableEmailPrefs,
889 $defaultPreferences[
'enotifminoredits'] = [
891 'section' =>
'personal/email',
892 'label-message' =>
'tog-enotifminoredits',
893 'disabled' => $disableEmailPrefs,
898 $defaultPreferences[
'enotifrevealaddr'] = [
900 'section' =>
'personal/email',
901 'label-message' =>
'tog-enotifrevealaddr',
902 'disabled' => $disableEmailPrefs,
918 if ( $skinOptions ) {
919 $defaultPreferences[
'skin'] = [
922 'options' => $skinOptions,
923 'section' =>
'rendering/skin',
925 $defaultPreferences[
'skin-responsive'] = [
927 'label-message' =>
'prefs-skin-responsive',
928 'section' =>
'rendering/skin/skin-prefs',
929 'help-message' =>
'prefs-help-skin-responsive',
938 if ( $allowUserCss || $allowUserJs ) {
942 if ( $allowUserCss ) {
943 $cssPage = Title::makeTitleSafe(
NS_USER, $userName .
'/common.css' );
944 $cssLinkText = $context->
msg(
'prefs-custom-css' )->text();
945 $linkTools[] = $this->linkRenderer->makeLink( $cssPage, $cssLinkText );
948 if ( $allowUserJs ) {
949 $jsPage = Title::makeTitleSafe(
NS_USER, $userName .
'/common.js' );
950 $jsLinkText = $context->
msg(
'prefs-custom-js' )->text();
951 $linkTools[] = $this->linkRenderer->makeLink( $jsPage, $jsLinkText );
954 $defaultPreferences[
'commoncssjs'] = [
957 'default' => $context->
getLanguage()->pipeList( $linkTools ),
958 'label-message' =>
'prefs-common-config',
959 'section' =>
'rendering/skin',
969 $defaultPreferences[
'imagesize'] = [
972 'label-message' =>
'imagemaxsize',
973 'section' =>
'rendering/files',
975 $defaultPreferences[
'thumbsize'] = [
978 'label-message' =>
'thumbsize',
979 'section' =>
'rendering/files',
993 if ( $dateOptions ) {
994 $defaultPreferences[
'date'] = [
996 'options' => $dateOptions,
997 'section' =>
'rendering/dateformat',
1004 $nowlocal =
Xml::element(
'span', [
'id' =>
'wpLocalTime' ],
1005 $lang->userTime( $now, $user ) );
1006 $nowserver =
$lang->userTime( $now, $user,
1007 [
'format' =>
false,
'timecorrection' =>
false ] ) .
1008 Html::hidden(
'wpServerTime', (
int)substr( $now, 8, 2 ) * 60 + (
int)substr( $now, 10, 2 ) );
1010 $defaultPreferences[
'nowserver'] = [
1013 'label-message' =>
'servertime',
1014 'default' => $nowserver,
1015 'section' =>
'rendering/timeoffset',
1018 $defaultPreferences[
'nowlocal'] = [
1021 'label-message' =>
'localtime',
1022 'default' => $nowlocal,
1023 'section' =>
'rendering/timeoffset',
1027 $tzOffset = $this->userOptionsManager->getOption( $user,
'timecorrection' );
1028 $tz = explode(
'|', $tzOffset, 3 );
1032 $tzSetting = $tzOffset;
1033 if ( count( $tz ) > 1 && $tz[0] ==
'ZoneInfo' &&
1034 !in_array( $tzOffset, HTMLFormField::flattenOptions( $tzOptions ) )
1038 $userTZ =
new DateTimeZone( $tz[2] );
1039 $minDiff = floor( $userTZ->getOffset(
new DateTime(
'now' ) ) / 60 );
1040 $tzSetting =
"ZoneInfo|$minDiff|{$tz[2]}";
1041 }
catch ( TimeoutException $e ) {
1043 }
catch ( Exception $e ) {
1048 if ( count( $tz ) > 1 && $tz[0] ==
'Offset' ) {
1049 $minDiff = (int)$tz[1];
1050 $tzSetting = sprintf(
'%+03d:%02d', floor( $minDiff / 60 ), abs( $minDiff ) % 60 );
1053 $defaultPreferences[
'timecorrection'] = [
1054 'class' => \HTMLSelectOrOtherField::class,
1055 'label-message' =>
'timezonelegend',
1056 'options' => $tzOptions,
1057 'default' => $tzSetting,
1059 'section' =>
'rendering/timeoffset',
1060 'id' =>
'wpTimeCorrection',
1061 'filter' => TimezoneFilter::class,
1062 'placeholder-message' =>
'timezone-useoffset-placeholder',
1074 &$defaultPreferences
1077 $defaultPreferences[
'diffonly'] = [
1079 'section' =>
'rendering/diffs',
1080 'label-message' =>
'tog-diffonly',
1082 $defaultPreferences[
'norollbackdiff'] = [
1084 'section' =>
'rendering/diffs',
1085 'label-message' =>
'tog-norollbackdiff',
1090 $defaultPreferences[
'underline'] = [
1093 $l10n->
msg(
'underline-never' )->text() => 0,
1094 $l10n->
msg(
'underline-always' )->text() => 1,
1095 $l10n->
msg(
'underline-default' )->text() => 2,
1097 'label-message' =>
'tog-underline',
1098 'section' =>
'rendering/advancedrendering',
1102 $defaultPreferences[
'showhiddencats'] = [
1104 'section' =>
'rendering/advancedrendering',
1105 'label-message' =>
'tog-showhiddencats'
1109 $defaultPreferences[
'showrollbackconfirmation'] = [
1111 'section' =>
'rendering/advancedrendering',
1112 'label-message' =>
'tog-showrollbackconfirmation',
1123 $defaultPreferences[
'editsectiononrightclick'] = [
1125 'section' =>
'editing/advancedediting',
1126 'label-message' =>
'tog-editsectiononrightclick',
1128 $defaultPreferences[
'editondblclick'] = [
1130 'section' =>
'editing/advancedediting',
1131 'label-message' =>
'tog-editondblclick',
1135 $defaultPreferences[
'editfont'] = [
1137 'section' =>
'editing/editor',
1138 'label-message' =>
'editfont-style',
1140 $l10n->
msg(
'editfont-monospace' )->text() =>
'monospace',
1141 $l10n->
msg(
'editfont-sansserif' )->text() =>
'sans-serif',
1142 $l10n->
msg(
'editfont-serif' )->text() =>
'serif',
1147 if ( $user->
isAllowed(
'minoredit' ) ) {
1148 $defaultPreferences[
'minordefault'] = [
1150 'section' =>
'editing/editor',
1151 'label-message' =>
'tog-minordefault',
1155 $defaultPreferences[
'forceeditsummary'] = [
1157 'section' =>
'editing/editor',
1158 'label-message' =>
'tog-forceeditsummary',
1160 $defaultPreferences[
'useeditwarning'] = [
1162 'section' =>
'editing/editor',
1163 'label-message' =>
'tog-useeditwarning',
1166 $defaultPreferences[
'previewonfirst'] = [
1168 'section' =>
'editing/preview',
1169 'label-message' =>
'tog-previewonfirst',
1171 $defaultPreferences[
'previewontop'] = [
1173 'section' =>
'editing/preview',
1174 'label-message' =>
'tog-previewontop',
1176 $defaultPreferences[
'uselivepreview'] = [
1178 'section' =>
'editing/preview',
1179 'label-message' =>
'tog-uselivepreview',
1190 $rcMax = ceil( $rcMaxAge / ( 3600 * 24 ) );
1191 $defaultPreferences[
'rcdays'] = [
1193 'label-message' =>
'recentchangesdays',
1194 'section' =>
'rc/displayrc',
1199 $defaultPreferences[
'rclimit'] = [
1203 'label-message' =>
'recentchangescount',
1204 'help-message' =>
'prefs-help-recentchangescount',
1205 'section' =>
'rc/displayrc',
1206 'filter' => IntvalFilter::class,
1208 $defaultPreferences[
'usenewrc'] = [
1210 'label-message' =>
'tog-usenewrc',
1211 'section' =>
'rc/advancedrc',
1213 $defaultPreferences[
'hideminor'] = [
1215 'label-message' =>
'tog-hideminor',
1216 'section' =>
'rc/changesrc',
1218 $defaultPreferences[
'pst-cssjs'] = [
1221 $defaultPreferences[
'rcfilters-rc-collapsed'] = [
1224 $defaultPreferences[
'rcfilters-wl-collapsed'] = [
1227 $defaultPreferences[
'rcfilters-saved-queries'] = [
1230 $defaultPreferences[
'rcfilters-wl-saved-queries'] = [
1234 $defaultPreferences[
'rcfilters-limit'] = [
1237 $defaultPreferences[
'rcfilters-saved-queries-versionbackup'] = [
1240 $defaultPreferences[
'rcfilters-wl-saved-queries-versionbackup'] = [
1245 $defaultPreferences[
'hidecategorization'] = [
1247 'label-message' =>
'tog-hidecategorization',
1248 'section' =>
'rc/changesrc',
1253 $defaultPreferences[
'hidepatrolled'] = [
1255 'section' =>
'rc/changesrc',
1256 'label-message' =>
'tog-hidepatrolled',
1261 $defaultPreferences[
'newpageshidepatrolled'] = [
1263 'section' =>
'rc/changesrc',
1264 'label-message' =>
'tog-newpageshidepatrolled',
1269 $defaultPreferences[
'shownumberswatching'] = [
1271 'section' =>
'rc/advancedrc',
1272 'label-message' =>
'tog-shownumberswatching',
1276 $defaultPreferences[
'rcenhancedfilters-disable'] = [
1278 'section' =>
'rc/advancedrc',
1279 'label-message' =>
'rcfilters-preference-label',
1280 'help-message' =>
'rcfilters-preference-help',
1294 if ( $user->
isAllowed(
'editmywatchlist' ) ) {
1295 $editWatchlistLinks =
'';
1296 $editWatchlistModes = [
1297 'edit' => [
'subpage' =>
false,
'flags' => [] ],
1298 'raw' => [
'subpage' =>
'raw',
'flags' => [] ],
1299 'clear' => [
'subpage' =>
'clear',
'flags' => [
'destructive' ] ],
1301 foreach ( $editWatchlistModes as $mode =>
$options ) {
1303 $editWatchlistLinks .=
1304 new \OOUI\ButtonWidget( [
1307 'label' =>
new \OOUI\HtmlSnippet(
1308 $context->
msg(
"prefs-editwatchlist-{$mode}" )->parse()
1313 $defaultPreferences[
'editwatchlist'] = [
1316 'default' => $editWatchlistLinks,
1317 'label-message' =>
'prefs-editwatchlist-label',
1318 'section' =>
'watchlist/editwatchlist',
1322 $defaultPreferences[
'watchlistdays'] = [
1325 'max' => $watchlistdaysMax,
1326 'section' =>
'watchlist/displaywatchlist',
1327 'help-message' => [
'prefs-watchlist-days-max',
Message::numParam( $watchlistdaysMax ) ],
1328 'label-message' =>
'prefs-watchlist-days',
1330 $defaultPreferences[
'wllimit'] = [
1334 'label-message' =>
'prefs-watchlist-edits',
1335 'help-message' =>
'prefs-watchlist-edits-max',
1336 'section' =>
'watchlist/displaywatchlist',
1337 'filter' => IntvalFilter::class,
1339 $defaultPreferences[
'extendwatchlist'] = [
1341 'section' =>
'watchlist/advancedwatchlist',
1342 'label-message' =>
'tog-extendwatchlist',
1344 $defaultPreferences[
'watchlisthideminor'] = [
1346 'section' =>
'watchlist/changeswatchlist',
1347 'label-message' =>
'tog-watchlisthideminor',
1349 $defaultPreferences[
'watchlisthidebots'] = [
1351 'section' =>
'watchlist/changeswatchlist',
1352 'label-message' =>
'tog-watchlisthidebots',
1354 $defaultPreferences[
'watchlisthideown'] = [
1356 'section' =>
'watchlist/changeswatchlist',
1357 'label-message' =>
'tog-watchlisthideown',
1359 $defaultPreferences[
'watchlisthideanons'] = [
1361 'section' =>
'watchlist/changeswatchlist',
1362 'label-message' =>
'tog-watchlisthideanons',
1364 $defaultPreferences[
'watchlisthideliu'] = [
1366 'section' =>
'watchlist/changeswatchlist',
1367 'label-message' =>
'tog-watchlisthideliu',
1371 $defaultPreferences[
'watchlistreloadautomatically'] = [
1373 'section' =>
'watchlist/advancedwatchlist',
1374 'label-message' =>
'tog-watchlistreloadautomatically',
1378 $defaultPreferences[
'watchlistunwatchlinks'] = [
1380 'section' =>
'watchlist/advancedwatchlist',
1381 'label-message' =>
'tog-watchlistunwatchlinks',
1385 $defaultPreferences[
'watchlisthidecategorization'] = [
1387 'section' =>
'watchlist/changeswatchlist',
1388 'label-message' =>
'tog-watchlisthidecategorization',
1393 $defaultPreferences[
'watchlisthidepatrolled'] = [
1395 'section' =>
'watchlist/changeswatchlist',
1396 'label-message' =>
'tog-watchlisthidepatrolled',
1401 'edit' =>
'watchdefault',
1402 'move' =>
'watchmoves',
1403 'delete' =>
'watchdeletion'
1407 if ( $user->
isAllowedAny(
'createpage',
'createtalk' ) ) {
1408 $watchTypes[
'read'] =
'watchcreations';
1412 $watchTypes[
'rollback'] =
'watchrollback';
1416 $watchTypes[
'upload'] =
'watchuploads';
1419 foreach ( $watchTypes as $action => $pref ) {
1424 $defaultPreferences[$pref] = [
1426 'section' =>
'watchlist/pageswatchlist',
1427 'label-message' =>
"tog-$pref",
1432 $defaultPreferences[
'watchlisttoken'] = [
1436 $tokenButton = new \OOUI\ButtonWidget( [
1440 'label' => $context->
msg(
'prefs-watchlist-managetokens' )->text(),
1442 $defaultPreferences[
'watchlisttoken-info'] = [
1444 'section' =>
'watchlist/tokenwatchlist',
1445 'label-message' =>
'prefs-watchlist-token',
1446 'help-message' =>
'prefs-help-tokenmanagement',
1448 'default' => (string)$tokenButton,
1451 $defaultPreferences[
'wlenhancedfilters-disable'] = [
1453 'section' =>
'watchlist/advancedwatchlist',
1454 'label-message' =>
'rcfilters-watchlist-preference-label',
1455 'help-message' =>
'rcfilters-watchlist-preference-help',
1464 $defaultPreferences[
'search-special-page'] = [
1468 foreach ( $this->nsInfo->getValidNamespaces() as $n ) {
1469 $defaultPreferences[
'searchNs' . $n] = [
1475 $defaultPreferences[
'search-match-redirect'] = [
1477 'section' =>
'searchoptions/searchmisc',
1478 'label-message' =>
'search-match-redirect-label',
1479 'help-message' =>
'search-match-redirect-help',
1482 $defaultPreferences[
'search-match-redirect'] = [
1487 $defaultPreferences[
'searchlimit'] = [
1491 'section' =>
'searchoptions/searchmisc',
1492 'label-message' =>
'searchlimit-label',
1493 'help-message' => $context->
msg(
'searchlimit-help', 500 ),
1494 'filter' => IntvalFilter::class,
1507 private static function sortSkinNames( $a, $b, $currentSkin, $preferredSkins ) {
1509 if ( strcasecmp( $a, $currentSkin ) === 0 ) {
1512 if ( strcasecmp( $b, $currentSkin ) === 0 ) {
1516 if ( count( $preferredSkins ) ) {
1517 $aPreferred = array_search( $a, $preferredSkins );
1518 $bPreferred = array_search( $b, $preferredSkins );
1521 if ( $aPreferred !==
false && $bPreferred ===
false ) {
1524 if ( $aPreferred ===
false && $bPreferred !==
false ) {
1529 if ( $aPreferred !==
false && $bPreferred !==
false ) {
1530 return strcasecmp( $aPreferred, $bPreferred );
1534 return strcasecmp( $a, $b );
1545 $mptitle = Title::newMainPage();
1546 $previewtext = $context->
msg(
'skin-preview' )->escaped();
1549 $validSkinNames = $this->skinFactory->getAllowedSkins();
1550 $allInstalledSkins = $this->skinFactory->getInstalledSkins();
1553 $useSkin = $context->
getRequest()->getRawVal(
'useskin' );
1554 if ( isset( $allInstalledSkins[$useSkin] )
1555 && $context->
msg(
"skinname-$useSkin" )->exists()
1557 $validSkinNames[$useSkin] = $useSkin;
1561 $currentUserSkin = $this->userOptionsManager->getOption( $user,
'skin' );
1562 if ( isset( $allInstalledSkins[$currentUserSkin] )
1563 && $context->
msg(
"skinname-$currentUserSkin" )->exists()
1565 $validSkinNames[$currentUserSkin] = $currentUserSkin;
1568 foreach ( $validSkinNames as $skinkey => &$skinname ) {
1569 $msg = $context->
msg(
"skinname-{$skinkey}" );
1570 if ( $msg->exists() ) {
1571 $skinname = htmlspecialchars( $msg->text() );
1579 uksort( $validSkinNames,
function ( $a, $b ) use ( $currentUserSkin, $preferredSkins ) {
1580 return $this->sortSkinNames( $a, $b, $currentUserSkin, $preferredSkins );
1586 $foundDefault =
false;
1587 foreach ( $validSkinNames as $skinkey => $sn ) {
1591 if ( strcasecmp( $skinkey, $defaultSkin ) === 0 ) {
1592 $linkTools[] = $context->
msg(
'default' )->escaped();
1593 $foundDefault =
true;
1597 $talkPageMsg = $context->
msg(
"$skinkey-prefs-talkpage" );
1598 if ( $talkPageMsg->exists() ) {
1599 $linkTools[] = $talkPageMsg->parse();
1603 $mplink = htmlspecialchars( $mptitle->getLocalURL( [
'useskin' => $skinkey ] ) );
1604 $linkTools[] =
"<a target='_blank' href=\"$mplink\">$previewtext</a>";
1608 if ( $allowUserCss ) {
1609 $cssPage = Title::makeTitleSafe(
NS_USER, $user->
getName() .
'/' . $skinkey .
'.css' );
1610 $cssLinkText = $context->
msg(
'prefs-custom-css' )->text();
1611 $linkTools[] = $this->linkRenderer->makeLink( $cssPage, $cssLinkText );
1614 if ( $allowUserJs ) {
1615 $jsPage = Title::makeTitleSafe(
NS_USER, $user->
getName() .
'/' . $skinkey .
'.js' );
1616 $jsLinkText = $context->
msg(
'prefs-custom-js' )->text();
1617 $linkTools[] = $this->linkRenderer->makeLink( $jsPage, $jsLinkText );
1620 $display = $sn .
' ' . $context->
msg(
'parentheses' )
1621 ->rawParams( $context->
getLanguage()->pipeList( $linkTools ) )
1623 $ret[$display] = $skinkey;
1626 if ( !$foundDefault ) {
1641 $dateopts =
$lang->getDatePreferences();
1646 if ( !in_array(
'default', $dateopts ) ) {
1647 $dateopts[] =
'default';
1657 foreach ( $dateopts as $key ) {
1658 if ( $key ==
'default' ) {
1659 $formatted = $context->
msg(
'datedefault' )->escaped();
1661 $formatted = htmlspecialchars(
$lang->timeanddate( $epoch,
false, $key ) );
1663 $ret[$formatted] = $key;
1675 $pixels = $l10n->
msg(
'unit-pixel' )->text();
1679 $display =
"{$limits[0]}\u{200E}×{$limits[1]}$pixels";
1680 $ret[$display] = $index;
1692 $pixels = $l10n->
msg(
'unit-pixel' )->text();
1695 $display = $size . $pixels;
1696 $ret[$display] = $index;
1711 if ( is_string( $signature ) && mb_strlen( $signature ) > $maxSigChars ) {
1712 return $form->
msg(
'badsiglength' )->numParams( $maxSigChars )->escaped();
1715 if ( $signature ===
null || $signature ===
'' ) {
1722 if ( !( isset( $alldata[
'fancysig'] ) && $alldata[
'fancysig'] ) ) {
1739 $signature === $this->userOptionsManager->getOption( $user,
'nickname' ) &&
1740 (
bool)$alldata[
'fancysig'] === $this->userOptionsManager->getBoolOption( $user,
'fancysig' )
1745 if ( $sigValidation ===
'new' || $sigValidation ===
'disallow' ) {
1747 $parserOpts = ParserOptions::newFromContext( $form->
getContext() );
1748 $validator = $this->signatureValidatorFactory
1749 ->newSignatureValidator( $user, $form->
getContext(), $parserOpts );
1750 $errors = $validator->validateSignature( $signature );
1759 if ( $this->parser->validateSig( $signature ) ===
false ) {
1760 return $form->
msg(
'badsig' )->escaped();
1773 if ( isset( $alldata[
'fancysig'] ) && $alldata[
'fancysig'] ) {
1774 $signature = $this->parser->cleanSig( $signature );
1793 $formClass = PreferencesFormOOUI::class,
1801 if ( count( $remove ) ) {
1802 $removeKeys = array_fill_keys( $remove,
true );
1803 $formDescriptor = array_diff_key( $formDescriptor, $removeKeys );
1807 foreach ( $formDescriptor as $name => $info ) {
1808 if ( isset( $info[
'type'] ) && $info[
'type'] ===
'api' ) {
1809 unset( $formDescriptor[$name] );
1816 $htmlForm =
new $formClass( $formDescriptor, $context,
'prefs' );
1822 $htmlForm->setAction( $context->
getTitle()->getLocalURL( [
1823 'useskin' => $context->
getRequest()->getRawVal(
'useskin' )
1826 $htmlForm->setModifiedUser( $user );
1827 $htmlForm->setOptionsEditable( $user->
isAllowed(
'editmyoptions' ) );
1828 $htmlForm->setPrivateInfoEditable( $user->
isAllowed(
'editmyprivateinfo' ) );
1829 $htmlForm->setId(
'mw-prefs-form' );
1830 $htmlForm->setAutocomplete(
'off' );
1831 $htmlForm->setSubmitTextMsg(
'saveprefs' );
1833 $htmlForm->setSubmitTooltip(
'preferences-save' );
1834 $htmlForm->setSubmitID(
'prefcontrol' );
1835 $htmlForm->setSubmitCallback(
1837 return $this->
submitForm( $formData, $form, $formDescriptor );
1854 $timestamp = MWTimestamp::getLocalInstance();
1856 if ( $localTZoffset === (
int)$timestamp->format(
'Z' ) / 60 ) {
1857 $timezoneName = $timestamp->getTimezone()->getName();
1859 if ( isset( $timeZoneList[$timezoneName] ) ) {
1860 $timezoneName = $timeZoneList[$timezoneName][
'name'];
1862 $server_tz_msg = $context->
msg(
1863 'timezoneuseserverdefault',
1867 $tzstring = sprintf(
1869 floor( $localTZoffset / 60 ),
1870 abs( $localTZoffset ) % 60
1872 $server_tz_msg = $context->
msg(
'timezoneuseserverdefault', $tzstring )->text();
1874 $opt[$server_tz_msg] =
"System|$localTZoffset";
1875 $opt[$context->
msg(
'timezoneuseoffset' )->text()] =
'other';
1876 $opt[$context->
msg(
'guesstimezone' )->text()] =
'guess';
1878 foreach ( $timeZoneList as $timeZoneInfo ) {
1879 $region = $timeZoneInfo[
'region'];
1880 if ( !isset( $opt[$region] ) ) {
1883 $opt[$region][$timeZoneInfo[
'name']] = $timeZoneInfo[
'timecorrection'];
1901 if ( !$user->
isAllowedAny(
'editmyprivateinfo',
'editmyoptions' )
1903 return Status::newFatal(
'mypreferencesprotected' );
1907 $this->
applyFilters( $formData, $formDescriptor,
'filterFromForm' );
1912 if ( !in_array(
'realname', $hiddenPrefs )
1913 && $user->
isAllowed(
'editmyprivateinfo' )
1914 && array_key_exists(
'realname', $formData )
1916 $realName = $formData[
'realname'];
1920 if ( $user->
isAllowed(
'editmyoptions' ) ) {
1921 $oldUserOptions = $this->userOptionsManager->getOptions( $user );
1924 unset( $formData[$b] );
1930 foreach ( $hiddenPrefs as $pref ) {
1933 $formData[$pref] = $this->userOptionsManager->getOption( $user, $pref,
null,
true );
1938 isset( $formData[
'rclimit'] ) &&
1939 intval( $formData[
'rclimit' ] ) !== $this->userOptionsManager->getIntOption( $user,
'rclimit' )
1941 $formData[
'rcfilters-limit'] = $formData[
'rclimit'];
1945 $this->userOptionsManager->resetOptions( $user, $form->
getContext(),
'unused' );
1947 foreach ( $formData as $key => $value ) {
1948 $this->userOptionsManager->setOption( $user, $key, $value );
1951 $this->hookRunner->onPreferencesFormPreSave(
1952 $formData, $form, $user, $result, $oldUserOptions );
1968 protected function applyFilters( array &$preferences, array $formDescriptor, $verb ) {
1969 foreach ( $formDescriptor as $preference => $desc ) {
1970 if ( !isset( $desc[
'filter'] ) || !isset( $preferences[$preference] ) ) {
1973 $filterDesc = $desc[
'filter'];
1974 if ( $filterDesc instanceof
Filter ) {
1975 $filter = $filterDesc;
1976 } elseif ( class_exists( $filterDesc ) ) {
1977 $filter =
new $filterDesc();
1978 } elseif ( is_callable( $filterDesc ) ) {
1979 $filter = $filterDesc();
1981 throw new UnexpectedValueException(
1982 "Unrecognized filter type for preference '$preference'"
1985 $preferences[$preference] = $filter->$verb( $preferences[$preference] );
2000 array $formDescriptor
2004 if (
$res ===
true ) {
2010 $url = $form->
getTitle()->getFullURL( $urlOptions );
2013 $context->
getRequest()->getSession()->set(
'specialPreferencesSaveSuccess', 1 );
2015 $context->
getOutput()->redirect( $url );
2018 return (
$res ===
true ? Status::newGood() :
$res );
2030 $identifiers = DateTimeZone::listIdentifiers();
2031 '@phan-var array|false $identifiers';
2032 if ( $identifiers ===
false ) {
2035 sort( $identifiers );
2038 'Africa' =>
wfMessage(
'timezoneregion-africa' )->inLanguage( $language )->text(),
2039 'America' =>
wfMessage(
'timezoneregion-america' )->inLanguage( $language )->text(),
2040 'Antarctica' =>
wfMessage(
'timezoneregion-antarctica' )->inLanguage( $language )->text(),
2041 'Arctic' =>
wfMessage(
'timezoneregion-arctic' )->inLanguage( $language )->text(),
2042 'Asia' =>
wfMessage(
'timezoneregion-asia' )->inLanguage( $language )->text(),
2043 'Atlantic' =>
wfMessage(
'timezoneregion-atlantic' )->inLanguage( $language )->text(),
2044 'Australia' =>
wfMessage(
'timezoneregion-australia' )->inLanguage( $language )->text(),
2045 'Europe' =>
wfMessage(
'timezoneregion-europe' )->inLanguage( $language )->text(),
2046 'Indian' =>
wfMessage(
'timezoneregion-indian' )->inLanguage( $language )->text(),
2047 'Pacific' =>
wfMessage(
'timezoneregion-pacific' )->inLanguage( $language )->text(),
2049 asort( $tzRegions );
2053 $now =
new DateTime();
2055 foreach ( $identifiers as $identifier ) {
2056 $parts = explode(
'/', $identifier, 2 );
2061 if ( count( $parts ) !== 2 || !array_key_exists( $parts[0], $tzRegions ) ) {
2066 $parts[0] = $tzRegions[$parts[0]];
2068 $dateTimeZone =
new DateTimeZone( $identifier );
2069 $minDiff = floor( $dateTimeZone->getOffset( $now ) / 60 );
2071 $display = str_replace(
'_',
' ', $parts[0] .
'/' . $parts[1] );
2072 $value =
"ZoneInfo|$minDiff|$identifier";
2074 $timeZoneList[$identifier] = [
2076 'timecorrection' => $value,
2077 'region' => $parts[0],
2081 return $timeZoneList;
wfTimestampNow()
Convenience function; returns MediaWiki timestamp for the present time.
wfMessage( $key,... $params)
This is the function for getting translated interface messages.
msg( $key,... $params)
Get a Message object with context set Parameters are the same as wfMessage()
getContext()
Get the base IContextSource object.
This class is a collection of static functions that serve two purposes:
Methods for dealing with language codes.
Base class for multi-variant language conversion.
Base class for language-specific code.
Library for creating and parsing MW-style timestamps.
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 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 EmailAuthentication
Name constant for the EmailAuthentication setting, for use with Config::get()
The Message class deals with fetching and processing of interface message into a variety of formats.
This is a utility class for dealing with namespaces that encodes all the "magic" behaviors of them ba...
This is one of the Core classes and should be read at least once by any new developers.
Set options of the Parser.
PHP Parser - Processes wiki markup (which uses a more user-friendly syntax, such as "[[link]]" for ma...
static stripOuterParagraph( $html)
Strip outer.
static cleanSigInSig( $text)
Strip 3, 4 or 5 tildes out of signatures.
Factory class to create Skin objects.
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,...
static checkStructuredFilterUiEnabled(UserIdentity $user)
Static method to check whether StructuredFilter UI is enabled for the given user.1....
Generic operation result class Has warning/error list, boolean status and arbitrary value.
Represents a title within MediaWiki.
Represents a "user group membership" – a specific instance of a user belonging to a group.
getName()
Get the user name, or the IP of an anonymous user.
getEmailAuthenticationTimestamp()
Get the timestamp of the user's e-mail authentication.
getRealName()
Get the user's real name.
getRegistration()
Get the timestamp of account creation.
isAllowedAny(... $permissions)
Checks whether this authority has any of the given permissions in general.
useNPPatrol()
Check whether to enable new pages patrol features for this user.
setRealName(string $str)
Set the user's real name.
useRCPatrol()
Check whether to enable recent changes patrol features for this user.
getEditCount()
Get the user's edit count.
getTitleKey()
Get the user's name escaped by underscores.
saveSettings()
Save this user's settings into the database.
getEmail()
Get the user's e-mail address.
isAllowed(string $permission)
Checks whether this authority has the given permission in general.
Module of static functions for generating XML.
static element( $element, $attribs=null, $contents='', $allowShortTag=true)
Format an XML element with given attributes and, optionally, text content.
$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.
The shared interface for all language converters.
Interface for localizing messages in MediaWiki.
msg( $key,... $params)
This is the method for getting translated interface messages.
if(!isset( $args[0])) $lang