76 private $userGroupManager =
null;
100 parent::__construct(
'Userrights' );
103 $this->userNameUtils = $userNameUtils ?? $services->getUserNameUtils();
104 $this->userNamePrefixSearch = $userNamePrefixSearch ?? $services->getUserNamePrefixSearch();
105 $this->userFactory = $userFactory ?? $services->getUserFactory();
106 $this->userGroupManagerFactory = $userGroupManagerFactory ?? $services->getUserGroupManagerFactory();
107 $this->actorStoreFactory = $actorStoreFactory ?? $services->getActorStoreFactory();
108 $this->watchlistManager = $watchlistManager ?? $services->getWatchlistManager();
129 $userGroupManager = $this->userGroupManagerFactory
130 ->getUserGroupManager( $targetUser->
getWikiId() );
136 if ( $available[
'add'] || $available[
'remove'] ) {
141 if ( ( $available[
'add-self'] || $available[
'remove-self'] )
142 && (
$isself || !$checkIfSelf )
161 $session = $request->getSession();
164 $out->addModules( [
'mediawiki.special.userrights' ] );
166 $this->mTarget = $par ?? $request->getVal(
'user' );
168 if ( is_string( $this->mTarget ) ) {
169 $this->mTarget = trim( $this->mTarget );
172 if ( $this->mTarget !==
null && $this->userNameUtils->getCanonical( $this->mTarget ) === $user->
getName() ) {
173 $this->isself =
true;
176 $fetchedStatus = $this->mTarget ===
null ? Status::newFatal(
'nouserspecified' ) :
177 $this->
fetchUser( $this->mTarget,
true );
178 if ( $fetchedStatus->isOK() ) {
179 $this->mFetchedUser = $fetchedUser = $fetchedStatus->value;
181 '@phan-var UserIdentity $fetchedUser';
182 $wikiId = $fetchedUser->getWikiId();
183 if ( $wikiId === UserIdentity::LOCAL ) {
186 $this->
getSkin()->setRelevantUser( $this->mFetchedUser );
188 $this->userGroupManager = $this->userGroupManagerFactory
189 ->getUserGroupManager( $wikiId );
194 $session->get(
'specialUserrightsSaveSuccess' ) &&
195 $this->mFetchedUser !==
null
198 $session->remove(
'specialUserrightsSaveSuccess' );
200 $out->addModuleStyles(
'mediawiki.notification.convertmessagebox.styles' );
206 $this->
msg(
'savedrights', $this->getDisplayUsername( $this->mFetchedUser ) )->text()
216 $out->addModuleStyles(
'mediawiki.special' );
217 $this->
addHelpLink(
'Help:Assigning permissions' );
222 $request->wasPosted() &&
223 $request->getCheck(
'saveusergroups' ) &&
224 $this->mTarget !==
null &&
225 $user->matchEditToken( $request->getVal(
'wpEditToken' ), $this->mTarget )
232 if ( !$this->
getAuthority()->isAllowed(
'userrights' ) ) {
233 $block = $user->getBlock();
234 if ( $block && $block->isSitewide() ) {
247 if ( !$fetchedStatus->isOK() ) {
248 $this->
getOutput()->addWikiTextAsInterface(
249 $fetchedStatus->getWikiText(
false,
false, $this->getLanguage() )
256 $conflictCheck = $request->getVal(
'conflictcheck-originalgroups' );
257 $conflictCheck = ( $conflictCheck ===
'' ) ? [] : explode(
',', $conflictCheck );
258 $userGroups = $this->userGroupManager->getUserGroups( $targetUser, IDBAccessObject::READ_LATEST );
260 if ( $userGroups !== $conflictCheck ) {
261 $out->addHTML( Html::errorBox(
262 $this->
msg(
'userrights-conflict' )->parse()
266 $request->getVal(
'user-reason' ),
270 if ( $status->isOK() ) {
272 $session->set(
'specialUserrightsSaveSuccess', 1 );
274 $out->redirect( $this->getSuccessURL() );
278 $out->wrapWikiTextAsInterface(
279 'error', $status->getWikiText(
false,
false, $this->getLanguage() )
286 if ( $this->mTarget !==
null ) {
287 $this->editUserGroupsForm( $this->mTarget );
291 private function getSuccessURL() {
292 return $this->
getPageTitle( $this->mTarget )->getFullURL();
319 $unix = strtotime( $expiry );
321 if ( !$unix || $unix === -1 ) {
339 if ( $this->userNameUtils->isTemp( $user->
getName() ) ) {
340 return Status::newFatal(
'userrights-no-tempuser' );
342 $allgroups = $this->userGroupManager->listAllGroups();
346 $existingUGMs = $this->userGroupManager->getUserGroupMemberships( $user );
350 foreach ( $allgroups as $group ) {
353 if ( $this->
getRequest()->getCheck(
"wpGroup-$group" ) ) {
354 $addgroup[] = $group;
358 $expiryDropdown = $this->
getRequest()->getVal(
"wpExpiry-$group" );
359 if ( $expiryDropdown ===
'existing' ) {
363 if ( $expiryDropdown ===
'other' ) {
364 $expiryValue = $this->
getRequest()->getVal(
"wpExpiry-$group-other" );
366 $expiryValue = $expiryDropdown;
372 if ( $groupExpiries[$group] ===
false ) {
373 return Status::newFatal(
'userrights-invalid-expiry', $group );
377 if ( $groupExpiries[$group] && $groupExpiries[$group] <
wfTimestampNow() ) {
378 return Status::newFatal(
'userrights-expiry-in-past', $group );
383 if ( !$this->canRemove( $group ) &&
384 isset( $existingUGMs[$group] ) &&
385 ( $existingUGMs[$group]->getExpiry() ?:
'infinity' ) >
386 ( $groupExpiries[$group] ?:
'infinity' )
388 return Status::newFatal(
'userrights-cannot-shorten-expiry', $group );
392 $removegroup[] = $group;
396 $this->
doSaveUserGroups( $user, $addgroup, $removegroup, $reason, [], $groupExpiries );
398 if ( $user->
getWikiId() === UserIdentity::LOCAL && $this->getRequest()->getCheck(
'wpWatch' ) ) {
399 $this->watchlistManager->addWatchIgnoringRights(
405 return Status::newGood();
424 array $tags = [], array $groupExpiries = []
428 if ( $this->userGroupManager !==
null ) {
430 $userGroupManager = $this->userGroupManager;
433 $userGroupManager = $this->userGroupManagerFactory
434 ->getUserGroupManager( $user->
getWikiId() );
439 $addable = array_merge( $changeable[
'add'],
$isself ? $changeable[
'add-self'] : [] );
440 $removable = array_merge( $changeable[
'remove'],
$isself ? $changeable[
'remove-self'] : [] );
442 $remove = array_unique( array_intersect( $remove, $removable, $groups ) );
443 $add = array_intersect( $add, $addable );
448 $add = array_filter( $add,
449 static function ( $group ) use ( $groups, $groupExpiries, $removable, $ugms ) {
450 if ( isset( $groupExpiries[$group] ) &&
451 !in_array( $group, $removable ) &&
452 isset( $ugms[$group] ) &&
453 ( $ugms[$group]->getExpiry() ?:
'infinity' ) >
454 ( $groupExpiries[$group] ?:
'infinity' )
458 return !in_array( $group, $groups ) || array_key_exists( $group, $groupExpiries );
461 if ( $user->
getWikiId() === UserIdentity::LOCAL ) {
463 $hookUser = $this->userFactory->newFromUserIdentity( $user );
470 $oldGroups = $groups;
472 $newGroups = $oldGroups;
476 foreach ( $remove as $index => $group ) {
478 unset( $remove[$index] );
481 $newGroups = array_diff( $newGroups, $remove );
484 foreach ( $add as $index => $group ) {
485 $expiry = $groupExpiries[$group] ??
null;
486 if ( !$userGroupManager->
addUserToGroup( $user, $group, $expiry,
true ) ) {
487 unset( $add[$index] );
490 $newGroups = array_merge( $newGroups, $add );
492 $newGroups = array_unique( $newGroups );
496 $this->userFactory->invalidateCache( $user );
499 $this->
getHookRunner()->onUserGroupsChanged( $hookUser, $add, $remove,
500 $this->
getUser(), $reason, $oldUGMs, $newUGMs );
502 wfDebug(
'oldGroups: ' . print_r( $oldGroups,
true ) );
503 wfDebug(
'newGroups: ' . print_r( $newGroups,
true ) );
504 wfDebug(
'oldUGMs: ' . print_r( $oldUGMs,
true ) );
505 wfDebug(
'newUGMs: ' . print_r( $newUGMs,
true ) );
508 if ( $newGroups != $oldGroups || $newUGMs != $oldUGMs ) {
509 $this->
addLogEntry( $user, $oldGroups, $newGroups, $reason, $tags, $oldUGMs, $newUGMs );
512 return [ $add, $remove ];
526 return [
'expiry' => $ugm->getExpiry() ];
539 protected function addLogEntry( $user, array $oldGroups, array $newGroups, $reason,
540 array $tags, array $oldUGMs, array $newUGMs
544 $oldUGMs = array_map(
static function ( $group ) use ( $oldUGMs ) {
545 return isset( $oldUGMs[$group] ) ?
549 $newUGMs = array_map(
static function ( $group ) use ( $newUGMs ) {
550 return isset( $newUGMs[$group] ) ?
556 $logEntry->setPerformer( $this->
getUser() );
557 $logEntry->setTarget( Title::makeTitle(
NS_USER, $this->getDisplayUsername( $user ) ) );
558 $logEntry->setComment( is_string( $reason ) ? $reason :
"" );
559 $logEntry->setParameters( [
560 '4::oldgroups' => $oldGroups,
561 '5::newgroups' => $newGroups,
562 'oldmetadata' => $oldUGMs,
563 'newmetadata' => $newUGMs,
565 $logid = $logEntry->insert();
566 if ( count( $tags ) ) {
567 $logEntry->addTags( $tags );
569 $logEntry->publish( $logid );
576 private function editUserGroupsForm( $username ) {
577 $status = $this->
fetchUser( $username,
true );
578 if ( !$status->isOK() ) {
579 $this->
getOutput()->addWikiTextAsInterface(
580 $status->getWikiText(
false,
false, $this->getLanguage() )
587 $user = $status->value;
588 '@phan-var UserIdentity $user';
590 $groups = $this->userGroupManager->getUserGroups( $user );
591 $groupMemberships = $this->userGroupManager->getUserGroupMemberships( $user );
608 public function fetchUser( $username, $writing =
true ) {
611 if ( count( $parts ) < 2 ) {
612 $name = trim( $username );
613 $wikiId = UserIdentity::LOCAL;
615 [ $name, $wikiId ] = array_map(
'trim', $parts );
617 if ( WikiMap::isCurrentWikiId( $wikiId ) ) {
618 $wikiId = UserIdentity::LOCAL;
621 !$this->
getAuthority()->isAllowed(
'userrights-interwiki' )
623 return Status::newFatal(
'userrights-no-interwiki' );
626 if ( !in_array( $wikiId, $localDatabases ) ) {
627 return Status::newFatal(
'userrights-nodatabase', $wikiId );
632 if ( $name ===
'' ) {
633 return Status::newFatal(
'nouserspecified' );
636 $userIdentityLookup = $this->actorStoreFactory->getUserIdentityLookup( $wikiId );
637 if ( $name[0] ==
'#' ) {
639 $id = intval( substr( $name, 1 ) );
641 $user = $userIdentityLookup->getUserIdentityByUserId( $id );
644 return Status::newFatal(
'noname' );
648 $name = $this->userNameUtils->getCanonical( $name );
649 if ( $name ===
false ) {
651 return Status::newFatal(
'nosuchusershort', $username );
653 $user = $userIdentityLookup->getUserIdentityByName( $name );
656 if ( $this->userNameUtils->isTemp( $name ) ) {
657 return Status::newFatal(
'userrights-no-group' );
661 return Status::newFatal(
'nosuchusershort', $username );
664 if ( $user->
getWikiId() === UserIdentity::LOCAL &&
665 $this->userFactory->newFromUserIdentity( $user )->isHidden() &&
666 !$this->getAuthority()->isAllowed(
'hideuser' )
669 return Status::newFatal(
'nosuchusershort', $username );
672 return Status::newGood( $user );
684 return $this->
msg(
'rightsnone' )->inContentLanguage()->text();
686 return implode(
', ', $ids );
694 $this->
getOutput()->addModules(
'mediawiki.userSuggest' );
703 'id' =>
'mw-userrights-form1'
706 Html::hidden(
'title', $this->
getPageTitle()->getPrefixedText() ) .
707 Xml::fieldset( $this->
msg(
'userrights-lookup-user' )->text() ) .
709 $this->
msg(
'userrights-user-editname' )->text(),
713 $this->mTarget !==
null ? str_replace(
'_',
' ', $this->mTarget ) :
'',
715 'class' =>
'mw-autocomplete-user',
718 $this->mFetchedUser ===
null ? [
'autofocus' =>
'' ] : []
722 $this->
msg(
'editusergroup' )->text()
724 Html::closeElement(
'fieldset' ) .
725 Html::closeElement(
'form' ) .
"\n"
739 $list = $membersList = $tempList = $tempMembersList = [];
740 foreach ( $groupMemberships as $ugm ) {
741 $linkG = UserGroupMembership::getLinkHTML( $ugm, $this->
getContext() );
742 $linkM = UserGroupMembership::getLinkHTML( $ugm, $this->
getContext(), $user->
getName() );
743 if ( $ugm->getExpiry() ) {
744 $tempList[] = $linkG;
745 $tempMembersList[] = $linkM;
748 $membersList[] = $linkM;
754 $autoMembersList = [];
756 if ( $user->
getWikiId() === UserIdentity::LOCAL ) {
758 foreach ( $this->userGroupManager->getUserAutopromoteGroups( $user ) as $group ) {
759 $autoList[] = UserGroupMembership::getLinkHTML( $group, $this->
getContext() );
760 $autoMembersList[] = UserGroupMembership::getLinkHTML( $group, $this->
getContext(), $user->
getName() );
765 $displayedList = $this->
msg(
'userrights-groupsmember-type' )
767 $language->commaList( array_merge( $tempList, $list ) ),
768 $language->commaList( array_merge( $tempMembersList, $membersList ) )
770 $displayedAutolist = $this->
msg(
'userrights-groupsmember-type' )
772 $language->commaList( $autoList ),
773 $language->commaList( $autoMembersList )
777 $count = count( $list ) + count( $tempList );
779 $grouplist = $this->
msg(
'userrights-groupsmember' )
780 ->numParams( $count )
783 $grouplist =
'<p>' . $grouplist .
' ' . $displayedList .
"</p>\n";
786 $count = count( $autoList );
788 $autogrouplistintro = $this->
msg(
'userrights-groupsmember-auto' )
789 ->numParams( $count )
792 $grouplist .=
'<p>' . $autogrouplistintro .
' ' . $displayedAutolist .
"</p>\n";
795 $systemUser = $user->
getWikiId() === UserIdentity::LOCAL
796 && $this->userFactory->newFromUserIdentity( $user )->isSystemUser();
798 $systemusernote = $this->
msg(
'userrights-systemuser' )
801 $grouplist .=
'<p>' . $systemusernote .
"</p>\n";
805 $flags = $systemUser ? 0 : Linker::TOOL_LINKS_EMAIL;
806 $userToolLinks = Linker::userToolLinks(
808 $this->getDisplayUsername( $user ),
813 [ $groupCheckboxes, $canChangeAny ] =
814 $this->groupCheckboxes( $groupMemberships, $user );
821 'name' =>
'editGroup',
822 'id' =>
'mw-userrights-form2'
825 Html::hidden(
'user', $this->mTarget ) .
826 Html::hidden(
'wpEditToken', $this->
getUser()->getEditToken( $this->mTarget ) ) .
828 'conflictcheck-originalgroups',
829 implode(
',', $this->userGroupManager->getUserGroups( $user ) )
831 Html::openElement(
'fieldset' ) .
836 $canChangeAny ?
'userrights-editusergroup' :
'userrights-viewusergroup',
841 $canChangeAny ?
'editinguser' :
'viewinguserrights'
843 ->rawParams( $userToolLinks )->parse()
845 if ( $canChangeAny ) {
847 $this->
msg(
'userrights-groups-help', $user->
getName() )->parse() .
850 Html::openElement(
'table', [
'id' =>
'mw-userrights-table-outer' ] ) .
852 <td class='mw-label'>" .
853 Html::label( $this->msg(
'userrights-reason' )->text(),
'wpReason' ) .
855 <td class='mw-input'>" .
856 Xml::input(
'user-reason', 60, $this->getRequest()->getVal(
'user-reason' ) ??
false, [
861 'maxlength' => CommentStore::COMMENT_CHARACTER_LIMIT,
867 <td class='mw-submit'>" .
868 Html::submitButton( $this->msg(
'saveusergroups', $user->
getName() )->text(),
869 [
'name' =>
'saveusergroups' ] +
870 Linker::tooltipAndAccesskeyAttribs(
'userrights-set' )
876 <td class='mw-input'>" .
877 Html::check(
'wpWatch',
false, [
'id' =>
'wpWatch' ] ) .
878 ' ' . Html::label( $this->msg(
'userrights-watchuser' )->text(),
'wpWatch' ) .
881 Xml::closeElement(
'table' ) .
"\n"
884 $this->
getOutput()->addHTML( $grouplist );
887 Xml::closeElement(
'fieldset' ) .
888 Xml::closeElement(
'form' ) .
"\n"
901 private function groupCheckboxes( $usergroups, $user ) {
902 $allgroups = $this->userGroupManager->listAllGroups();
906 $expiryOptionsMsg = $this->
msg(
'userrights-expiry-options' )->inContentLanguage();
907 $expiryOptions = $expiryOptionsMsg->isDisabled()
909 : XmlSelect::parseOptionsMessage( $expiryOptionsMsg->text() );
913 $columns = [
'unchangeable' => [],
'changeable' => [] ];
915 foreach ( $allgroups as $group ) {
916 $set = isset( $usergroups[$group] );
920 $canOnlyLengthenExpiry = ( $set && $this->canAdd( $group ) &&
921 !$this->canRemove( $group ) && $usergroups[$group]->getExpiry() );
923 $disabledCheckbox = !(
924 ( $set && $this->canRemove( $group ) ) ||
925 ( !$set && $this->canAdd( $group ) ) );
927 $disabledExpiry = $disabledCheckbox && !$canOnlyLengthenExpiry;
929 $irreversible = !$disabledCheckbox && (
930 ( $set && !$this->canAdd( $group ) ) ||
931 ( !$set && !$this->canRemove( $group ) ) );
935 'disabled' => $disabledCheckbox,
936 'disabled-expiry' => $disabledExpiry,
937 'irreversible' => $irreversible
940 if ( $disabledCheckbox && $disabledExpiry ) {
941 $columns[
'unchangeable'][$group] = $checkbox;
943 $columns[
'changeable'][$group] = $checkbox;
948 $ret .=
Xml::openElement(
'table', [
'class' =>
'mw-userrights-groups' ] ) .
950 foreach ( $columns as $name => $column ) {
951 if ( $column === [] ) {
958 $this->
msg(
'userrights-' . $name .
'-col', count( $column ) )->text()
962 $ret .=
"</tr>\n<tr>\n";
965 foreach ( $columns as $column ) {
966 if ( $column === [] ) {
969 $ret .=
"\t<td style='vertical-align:top;'>\n";
970 foreach ( $column as $group => $checkbox ) {
971 $member = $uiLanguage->getGroupMemberName( $group, $userName );
972 if ( $checkbox[
'irreversible'] ) {
973 $text = $this->
msg(
'userrights-irreversible-marker', $member )->text();
974 } elseif ( $checkbox[
'disabled'] && !$checkbox[
'disabled-expiry'] ) {
975 $text = $this->
msg(
'userrights-no-shorten-expiry-marker', $member )->text();
980 'type' =>
'checkbox',
'name' =>
"wpGroup-$group",
'value' =>
'1',
981 'id' =>
"wpGroup-$group",
'checked' => $checkbox[
'set'],
982 'class' =>
'mw-userrights-groupcheckbox',
983 'disabled' => $checkbox[
'disabled'],
984 ] ) .
' ' . Html::label( $text,
"wpGroup-$group" );
989 $currentExpiry = isset( $usergroups[$group] ) ?
990 $usergroups[$group]->getExpiry() :
995 if ( $checkbox[
'set'] &&
996 ( $checkbox[
'irreversible'] || $checkbox[
'disabled-expiry'] )
998 if ( $currentExpiry ) {
999 $expiryFormatted = $uiLanguage->userTimeAndDate( $currentExpiry, $uiUser );
1000 $expiryFormattedD = $uiLanguage->userDate( $currentExpiry, $uiUser );
1001 $expiryFormattedT = $uiLanguage->userTime( $currentExpiry, $uiUser );
1003 $this->
msg(
'userrights-expiry-current' )->params(
1004 $expiryFormatted, $expiryFormattedD, $expiryFormattedT )->text() );
1007 $this->
msg(
'userrights-expiry-none' )->text() );
1011 $expiryHtml .= Html::hidden(
"wpExpiry-$group",
1012 $currentExpiry ?
'existing' :
'infinite' );
1013 $expiryHtml .=
"<br />\n";
1016 $this->
msg(
'userrights-expiry' )->text() );
1017 $expiryHtml .= Html::openElement(
'span' );
1022 "mw-input-wpExpiry-$group",
1023 $currentExpiry ?
'existing' :
'infinite'
1025 if ( $checkbox[
'disabled-expiry'] ) {
1026 $expiryFormOptions->
setAttribute(
'disabled',
'disabled' );
1029 if ( $currentExpiry ) {
1030 $timestamp = $uiLanguage->userTimeAndDate( $currentExpiry, $uiUser );
1031 $d = $uiLanguage->userDate( $currentExpiry, $uiUser );
1032 $t = $uiLanguage->userTime( $currentExpiry, $uiUser );
1033 $existingExpiryMessage = $this->
msg(
'userrights-expiry-existing',
1034 $timestamp, $d, $t );
1035 $expiryFormOptions->addOption( $existingExpiryMessage->text(),
'existing' );
1038 $expiryFormOptions->addOption(
1039 $this->
msg(
'userrights-expiry-none' )->text(),
1042 $expiryFormOptions->addOption(
1043 $this->
msg(
'userrights-expiry-othertime' )->text(),
1047 $expiryFormOptions->addOptions( $expiryOptions );
1050 $expiryHtml .= $expiryFormOptions->getHTML() .
'<br />';
1054 'name' =>
"wpExpiry-$group-other",
'size' => 30,
'value' =>
'',
1055 'id' =>
"mw-input-wpExpiry-$group-other",
1056 'class' =>
'mw-userrights-expiryfield',
1057 'disabled' => $checkbox[
'disabled-expiry'],
1062 if ( $checkbox[
'set'] && $checkbox[
'disabled'] ) {
1063 $expiryHtml .= Html::hidden(
"wpGroup-$group", 1 );
1066 $expiryHtml .= Html::closeElement(
'span' );
1070 'id' =>
"mw-userrights-nested-wpGroup-$group",
1071 'class' =>
'mw-userrights-nested',
1073 $checkboxHtml .=
"\t\t\t" . Html::rawElement(
'div', $divAttribs, $expiryHtml ) .
"\n";
1075 $ret .=
"\t\t" . ( ( $checkbox[
'disabled'] && $checkbox[
'disabled-expiry'] )
1076 ? Html::rawElement(
'div', [
'class' =>
'mw-userrights-disabled' ], $checkboxHtml )
1077 : Html::rawElement(
'div', [], $checkboxHtml )
1080 $ret .=
"\t</td>\n";
1082 $ret .= Html::closeElement(
'tr' ) . Html::closeElement(
'table' );
1084 return [ $ret, (bool)$columns[
'changeable'] ];
1091 private function canRemove( $group ) {
1096 $groups[
'remove'] ) || ( $this->isself && in_array( $group, $groups[
'remove-self'] )
1104 private function canAdd( $group ) {
1109 $groups[
'add'] ) || ( $this->isself && in_array( $group, $groups[
'add-self'] )
1134 private function getDisplayUsername(
UserIdentity $user ) {
1136 if ( $user->
getWikiId() !== UserIdentity::LOCAL ) {
1150 $rightsLogPage =
new LogPage(
'rights' );
1151 $output->addHTML(
Html::element(
'h2', [], $rightsLogPage->getName()->text() ) );
1152 LogEventsList::showLogExtract( $output,
'rights',
1153 Title::makeTitle(
NS_USER, $this->getDisplayUsername( $user ) ) );
1165 $search = $this->userNameUtils->getCanonical( $search );
1171 return $this->userNamePrefixSearch
1172 ->search( UserNamePrefixSearch::AUDIENCE_PUBLIC, $search, $limit, $offset );
1184class_alias( SpecialUserRights::class,
'UserrightsPage' );
wfDebug( $text, $dest='all', array $context=[])
Sends a line to the debug log if enabled or, optionally, to a comment in output.
wfTimestampNow()
Convenience function; returns MediaWiki timestamp for the present time.
wfEscapeWikiText( $input)
Escapes the given text so that it may be output using addWikiText() without any linking,...
wfScript( $script='index')
Get the URL path to a MediaWiki entry point.
wfIsInfinity( $str)
Determine input string is represents as infinity.
wfTimestamp( $outputtype=TS_UNIX, $ts=0)
Get a timestamp string in one of various formats.
Class to simplify the use of log pages.
Class for creating new log entries and inserting them into the database.
A class containing constants representing the names of configuration variables.
const LocalDatabases
Name constant for the LocalDatabases setting, for use with Config::get()
const UserrightsInterwikiDelimiter
Name constant for the UserrightsInterwikiDelimiter 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.
setHeaders()
Sets headers - this should be called from the execute() method of all derived classes!
getSkin()
Shortcut to get the skin being used for this instance.
getUser()
Shortcut to get the User executing this instance.
getPageTitle( $subpage=false)
Get a self-referential title object.
checkReadOnly()
If the wiki is currently in readonly mode, throws a ReadOnlyError.
getConfig()
Shortcut to get main config object.
getContext()
Gets the context this SpecialPage is executed in.
getRequest()
Get the WebRequest being used for this instance.
msg( $key,... $params)
Wrapper around wfMessage that sets the current context.
getOutput()
Get the OutputPage being used for this instance.
getAuthority()
Shortcut to get the Authority executing this instance.
getLanguage()
Shortcut to get user's language.
outputHeader( $summaryMessageKey='')
Outputs a summary message on top of special pages Per default the message key is the canonical name o...
addHelpLink( $to, $overrideBaseUrl=false)
Adds help link with an icon via page indicators.
Show an error when a user tries to do something they do not have the necessary permissions for.
Show an error when the user tries to do something whilst blocked.
Class for generating HTML <select> or <datalist> elements.
setAttribute( $name, $value)
Module of static functions for generating XML.
static openElement( $element, $attribs=null)
This opens an XML element.
static element( $element, $attribs=null, $contents='', $allowShortTag=true)
Format an XML element with given attributes and, optionally, text content.
Interface for database access objects.