73 private $userGroupManager =
null;
97 parent::__construct(
'Userrights' );
100 $this->userNameUtils = $userNameUtils ?? $services->getUserNameUtils();
101 $this->userNamePrefixSearch = $userNamePrefixSearch ?? $services->getUserNamePrefixSearch();
102 $this->userFactory = $userFactory ?? $services->getUserFactory();
103 $this->userGroupManagerFactory = $userGroupManagerFactory ?? $services->getUserGroupManagerFactory();
104 $this->actorStoreFactory = $actorStoreFactory ?? $services->getActorStoreFactory();
105 $this->watchlistManager = $watchlistManager ?? $services->getWatchlistManager();
126 $userGroupManager = $this->userGroupManagerFactory
127 ->getUserGroupManager( $targetUser->
getWikiId() );
133 if ( $available[
'add'] || $available[
'remove'] ) {
138 if ( ( $available[
'add-self'] || $available[
'remove-self'] )
139 && (
$isself || !$checkIfSelf )
158 $session = $request->getSession();
161 $out->addModules( [
'mediawiki.special.userrights' ] );
163 $this->mTarget = $par ?? $request->getVal(
'user' );
164 if ( $this->mTarget ===
null ) {
165 $fetchedStatus = Status::newFatal(
'nouserspecified' );
168 $this->mTarget = trim( $this->mTarget );
170 if ( $this->userNameUtils->getCanonical( $this->mTarget ) === $user->
getName() ) {
171 $this->isself =
true;
174 $fetchedStatus = $this->
fetchUser( $this->mTarget,
true );
177 if ( $fetchedStatus->isOK() ) {
178 $this->mFetchedUser = $fetchedUser = $fetchedStatus->value;
180 '@phan-var UserIdentity $fetchedUser';
181 $wikiId = $fetchedUser->getWikiId();
182 if ( $wikiId === UserIdentity::LOCAL ) {
185 $this->
getSkin()->setRelevantUser( $this->mFetchedUser );
187 $this->userGroupManager = $this->userGroupManagerFactory
188 ->getUserGroupManager( $wikiId );
193 $session->get(
'specialUserrightsSaveSuccess' ) &&
194 $this->mFetchedUser !==
null
197 $session->remove(
'specialUserrightsSaveSuccess' );
199 $out->addModuleStyles(
'mediawiki.notification.convertmessagebox.styles' );
205 $this->
msg(
'savedrights', $this->getDisplayUsername( $this->mFetchedUser ) )->text()
215 $out->addModuleStyles(
'mediawiki.special' );
216 $this->
addHelpLink(
'Help:Assigning permissions' );
221 $request->wasPosted() &&
222 $request->getCheck(
'saveusergroups' ) &&
223 $this->mTarget !==
null &&
224 $user->matchEditToken( $request->getVal(
'wpEditToken' ), $this->mTarget )
231 if ( !$this->
getAuthority()->isAllowed(
'userrights' ) ) {
232 $block = $user->getBlock();
233 if ( $block && $block->isSitewide() ) {
246 if ( !$fetchedStatus->isOK() ) {
247 $this->
getOutput()->addWikiTextAsInterface(
248 $fetchedStatus->getWikiText(
false,
false, $this->getLanguage() )
255 $conflictCheck = $request->getVal(
'conflictcheck-originalgroups' );
256 $conflictCheck = ( $conflictCheck ===
'' ) ? [] : explode(
',', $conflictCheck );
257 $userGroups = $this->userGroupManager->getUserGroups( $targetUser, IDBAccessObject::READ_LATEST );
259 if ( $userGroups !== $conflictCheck ) {
260 $out->addHTML( Html::errorBox(
261 $this->
msg(
'userrights-conflict' )->parse()
265 $request->getText(
'user-reason' ),
269 if ( $status->isOK() ) {
271 $session->set(
'specialUserrightsSaveSuccess', 1 );
273 $out->redirect( $this->getSuccessURL() );
277 $out->wrapWikiTextAsInterface(
278 'error', $status->getWikiText(
false,
false, $this->getLanguage() )
285 if ( $this->mTarget !==
null ) {
286 $this->editUserGroupsForm( $this->mTarget );
290 private function getSuccessURL() {
291 return $this->
getPageTitle( $this->mTarget )->getFullURL();
318 $unix = strtotime( $expiry );
320 if ( !$unix || $unix === -1 ) {
338 if ( $this->userNameUtils->isTemp( $user->
getName() ) ) {
339 return Status::newFatal(
'userrights-no-tempuser' );
341 $allgroups = $this->userGroupManager->listAllGroups();
345 $existingUGMs = $this->userGroupManager->getUserGroupMemberships( $user );
349 foreach ( $allgroups as $group ) {
352 if ( $this->
getRequest()->getCheck(
"wpGroup-$group" ) ) {
353 $addgroup[] = $group;
357 $expiryDropdown = $this->
getRequest()->getVal(
"wpExpiry-$group" );
358 if ( $expiryDropdown ===
'existing' ) {
362 if ( $expiryDropdown ===
'other' ) {
363 $expiryValue = $this->
getRequest()->getVal(
"wpExpiry-$group-other" );
365 $expiryValue = $expiryDropdown;
371 if ( $groupExpiries[$group] ===
false ) {
372 return Status::newFatal(
'userrights-invalid-expiry', $group );
376 if ( $groupExpiries[$group] && $groupExpiries[$group] <
wfTimestampNow() ) {
377 return Status::newFatal(
'userrights-expiry-in-past', $group );
382 if ( !$this->canRemove( $group ) &&
383 isset( $existingUGMs[$group] ) &&
384 ( $existingUGMs[$group]->getExpiry() ?:
'infinity' ) >
385 ( $groupExpiries[$group] ?:
'infinity' )
387 return Status::newFatal(
'userrights-cannot-shorten-expiry', $group );
391 $removegroup[] = $group;
395 $this->
doSaveUserGroups( $user, $addgroup, $removegroup, $reason, [], $groupExpiries );
397 if ( $user->
getWikiId() === UserIdentity::LOCAL && $this->getRequest()->getCheck(
'wpWatch' ) ) {
398 $this->watchlistManager->addWatchIgnoringRights(
404 return Status::newGood();
423 array $tags = [], array $groupExpiries = []
427 if ( $this->userGroupManager !==
null ) {
429 $userGroupManager = $this->userGroupManager;
432 $userGroupManager = $this->userGroupManagerFactory
433 ->getUserGroupManager( $user->
getWikiId() );
438 $addable = array_merge( $changeable[
'add'],
$isself ? $changeable[
'add-self'] : [] );
439 $removable = array_merge( $changeable[
'remove'],
$isself ? $changeable[
'remove-self'] : [] );
441 $remove = array_unique( array_intersect( $remove, $removable, $groups ) );
442 $add = array_intersect( $add, $addable );
447 $add = array_filter( $add,
448 static function ( $group ) use ( $groups, $groupExpiries, $removable, $ugms ) {
449 if ( isset( $groupExpiries[$group] ) &&
450 !in_array( $group, $removable ) &&
451 isset( $ugms[$group] ) &&
452 ( $ugms[$group]->getExpiry() ?:
'infinity' ) >
453 ( $groupExpiries[$group] ?:
'infinity' )
457 return !in_array( $group, $groups ) || array_key_exists( $group, $groupExpiries );
460 if ( $user->
getWikiId() === UserIdentity::LOCAL ) {
462 $hookUser = $this->userFactory->newFromUserIdentity( $user );
469 $oldGroups = $groups;
471 $newGroups = $oldGroups;
475 foreach ( $remove as $index => $group ) {
477 unset( $remove[$index] );
480 $newGroups = array_diff( $newGroups, $remove );
483 foreach ( $add as $index => $group ) {
484 $expiry = $groupExpiries[$group] ??
null;
485 if ( !$userGroupManager->
addUserToGroup( $user, $group, $expiry,
true ) ) {
486 unset( $add[$index] );
489 $newGroups = array_merge( $newGroups, $add );
491 $newGroups = array_unique( $newGroups );
495 $this->userFactory->invalidateCache( $user );
498 $this->
getHookRunner()->onUserGroupsChanged( $hookUser, $add, $remove,
499 $this->
getUser(), $reason, $oldUGMs, $newUGMs );
501 wfDebug(
'oldGroups: ' . print_r( $oldGroups,
true ) );
502 wfDebug(
'newGroups: ' . print_r( $newGroups,
true ) );
503 wfDebug(
'oldUGMs: ' . print_r( $oldUGMs,
true ) );
504 wfDebug(
'newUGMs: ' . print_r( $newUGMs,
true ) );
507 if ( $newGroups != $oldGroups || $newUGMs != $oldUGMs ) {
508 $this->
addLogEntry( $user, $oldGroups, $newGroups, $reason, $tags, $oldUGMs, $newUGMs );
511 return [ $add, $remove ];
525 return [
'expiry' => $ugm->getExpiry() ];
538 protected function addLogEntry( $user, array $oldGroups, array $newGroups,
string $reason,
539 array $tags, array $oldUGMs, array $newUGMs
543 $oldUGMs = array_map(
static function ( $group ) use ( $oldUGMs ) {
544 return isset( $oldUGMs[$group] ) ?
548 $newUGMs = array_map(
static function ( $group ) use ( $newUGMs ) {
549 return isset( $newUGMs[$group] ) ?
555 $logEntry->setPerformer( $this->
getUser() );
556 $logEntry->setTarget( Title::makeTitle(
NS_USER, $this->getDisplayUsername( $user ) ) );
557 $logEntry->setComment( $reason );
558 $logEntry->setParameters( [
559 '4::oldgroups' => $oldGroups,
560 '5::newgroups' => $newGroups,
561 'oldmetadata' => $oldUGMs,
562 'newmetadata' => $newUGMs,
564 $logid = $logEntry->insert();
565 if ( count( $tags ) ) {
566 $logEntry->addTags( $tags );
568 $logEntry->publish( $logid );
575 private function editUserGroupsForm( $username ) {
576 $status = $this->
fetchUser( $username,
true );
577 if ( !$status->isOK() ) {
578 $this->
getOutput()->addWikiTextAsInterface(
579 $status->getWikiText(
false,
false, $this->getLanguage() )
586 $user = $status->value;
587 '@phan-var UserIdentity $user';
589 $groups = $this->userGroupManager->getUserGroups( $user );
590 $groupMemberships = $this->userGroupManager->getUserGroupMemberships( $user );
607 public function fetchUser( $username, $writing =
true ) {
610 if ( count( $parts ) < 2 ) {
611 $name = trim( $username );
612 $wikiId = UserIdentity::LOCAL;
614 [ $name, $wikiId ] = array_map(
'trim', $parts );
616 if ( WikiMap::isCurrentWikiId( $wikiId ) ) {
617 $wikiId = UserIdentity::LOCAL;
620 !$this->
getAuthority()->isAllowed(
'userrights-interwiki' )
622 return Status::newFatal(
'userrights-no-interwiki' );
625 if ( !in_array( $wikiId, $localDatabases ) ) {
626 return Status::newFatal(
'userrights-nodatabase', $wikiId );
631 if ( $name ===
'' ) {
632 return Status::newFatal(
'nouserspecified' );
635 $userIdentityLookup = $this->actorStoreFactory->getUserIdentityLookup( $wikiId );
636 if ( $name[0] ==
'#' ) {
638 $id = intval( substr( $name, 1 ) );
640 $user = $userIdentityLookup->getUserIdentityByUserId( $id );
643 return Status::newFatal(
'noname' );
647 $name = $this->userNameUtils->getCanonical( $name );
648 if ( $name ===
false ) {
650 return Status::newFatal(
'nosuchusershort', $username );
652 $user = $userIdentityLookup->getUserIdentityByName( $name );
655 if ( $this->userNameUtils->isTemp( $name ) ) {
656 return Status::newFatal(
'userrights-no-group' );
660 return Status::newFatal(
'nosuchusershort', $username );
663 if ( $user->
getWikiId() === UserIdentity::LOCAL &&
664 $this->userFactory->newFromUserIdentity( $user )->isHidden() &&
665 !$this->getAuthority()->isAllowed(
'hideuser' )
668 return Status::newFatal(
'nosuchusershort', $username );
671 return Status::newGood( $user );
683 return $this->
msg(
'rightsnone' )->inContentLanguage()->text();
685 return implode(
', ', $ids );
693 $this->
getOutput()->addModules(
'mediawiki.userSuggest' );
702 'id' =>
'mw-userrights-form1'
705 Html::hidden(
'title', $this->
getPageTitle()->getPrefixedText() ) .
706 Xml::fieldset( $this->
msg(
'userrights-lookup-user' )->text() ) .
708 $this->
msg(
'userrights-user-editname' )->text(),
712 $this->mTarget !==
null ? str_replace(
'_',
' ', $this->mTarget ) :
'',
714 'class' =>
'mw-autocomplete-user',
717 $this->mFetchedUser ===
null ? [
'autofocus' =>
'' ] : []
721 $this->
msg(
'editusergroup' )->text()
723 Html::closeElement(
'fieldset' ) .
724 Html::closeElement(
'form' ) .
"\n"
738 $list = $membersList = $tempList = $tempMembersList = [];
739 foreach ( $groupMemberships as $ugm ) {
740 $linkG = UserGroupMembership::getLinkHTML( $ugm, $this->
getContext() );
741 $linkM = UserGroupMembership::getLinkHTML( $ugm, $this->
getContext(), $user->
getName() );
742 if ( $ugm->getExpiry() ) {
743 $tempList[] = $linkG;
744 $tempMembersList[] = $linkM;
747 $membersList[] = $linkM;
753 $autoMembersList = [];
755 if ( $user->
getWikiId() === UserIdentity::LOCAL ) {
757 foreach ( $this->userGroupManager->getUserAutopromoteGroups( $user ) as $group ) {
758 $autoList[] = UserGroupMembership::getLinkHTML( $group, $this->
getContext() );
759 $autoMembersList[] = UserGroupMembership::getLinkHTML( $group, $this->
getContext(), $user->
getName() );
764 $displayedList = $this->
msg(
'userrights-groupsmember-type' )
766 $language->commaList( array_merge( $tempList, $list ) ),
767 $language->commaList( array_merge( $tempMembersList, $membersList ) )
769 $displayedAutolist = $this->
msg(
'userrights-groupsmember-type' )
771 $language->commaList( $autoList ),
772 $language->commaList( $autoMembersList )
776 $count = count( $list ) + count( $tempList );
778 $grouplist = $this->
msg(
'userrights-groupsmember' )
779 ->numParams( $count )
782 $grouplist =
'<p>' . $grouplist .
' ' . $displayedList .
"</p>\n";
785 $count = count( $autoList );
787 $autogrouplistintro = $this->
msg(
'userrights-groupsmember-auto' )
788 ->numParams( $count )
791 $grouplist .=
'<p>' . $autogrouplistintro .
' ' . $displayedAutolist .
"</p>\n";
794 $systemUser = $user->
getWikiId() === UserIdentity::LOCAL
795 && $this->userFactory->newFromUserIdentity( $user )->isSystemUser();
797 $systemusernote = $this->
msg(
'userrights-systemuser' )
800 $grouplist .=
'<p>' . $systemusernote .
"</p>\n";
804 $flags = $systemUser ? 0 : Linker::TOOL_LINKS_EMAIL;
805 $userToolLinks = Linker::userToolLinks(
807 $this->getDisplayUsername( $user ),
812 [ $groupCheckboxes, $canChangeAny ] =
813 $this->groupCheckboxes( $groupMemberships, $user );
820 'name' =>
'editGroup',
821 'id' =>
'mw-userrights-form2'
824 Html::hidden(
'user', $this->mTarget ) .
825 Html::hidden(
'wpEditToken', $this->
getUser()->getEditToken( $this->mTarget ) ) .
827 'conflictcheck-originalgroups',
828 implode(
',', $this->userGroupManager->getUserGroups( $user ) )
830 Html::openElement(
'fieldset' ) .
835 $canChangeAny ?
'userrights-editusergroup' :
'userrights-viewusergroup',
840 $canChangeAny ?
'editinguser' :
'viewinguserrights'
842 ->rawParams( $userToolLinks )->parse()
844 if ( $canChangeAny ) {
846 $this->
msg(
'userrights-groups-help', $user->
getName() )->parse() .
849 Html::openElement(
'table', [
'id' =>
'mw-userrights-table-outer' ] ) .
851 <td class='mw-label'>" .
852 Html::label( $this->msg(
'userrights-reason' )->text(),
'wpReason' ) .
854 <td class='mw-input'>" .
855 Xml::input(
'user-reason', 60, $this->getRequest()->getVal(
'user-reason' ) ??
false, [
860 'maxlength' => CommentStore::COMMENT_CHARACTER_LIMIT,
866 <td class='mw-submit'>" .
867 Html::submitButton( $this->msg(
'saveusergroups', $user->
getName() )->text(),
868 [
'name' =>
'saveusergroups' ] +
869 Linker::tooltipAndAccesskeyAttribs(
'userrights-set' )
875 <td class='mw-input'>" .
876 Html::check(
'wpWatch',
false, [
'id' =>
'wpWatch' ] ) .
877 ' ' . Html::label( $this->msg(
'userrights-watchuser' )->text(),
'wpWatch' ) .
883 $this->
getOutput()->addHTML( $grouplist );
900 private function groupCheckboxes( $usergroups,
UserIdentity $user ) {
901 $allgroups = $this->userGroupManager->listAllGroups();
905 $expiryOptionsMsg = $this->
msg(
'userrights-expiry-options' )->inContentLanguage();
906 $expiryOptions = $expiryOptionsMsg->isDisabled()
908 : XmlSelect::parseOptionsMessage( $expiryOptionsMsg->text() );
912 $columns = [
'unchangeable' => [],
'changeable' => [] ];
914 foreach ( $allgroups as $group ) {
915 $set = isset( $usergroups[$group] );
919 $canOnlyLengthenExpiry = ( $set && $this->canAdd( $group ) &&
920 !$this->canRemove( $group ) && $usergroups[$group]->getExpiry() );
922 $disabledCheckbox = !(
923 ( $set && $this->canRemove( $group ) ) ||
924 ( !$set && $this->canAdd( $group ) ) );
926 $disabledExpiry = $disabledCheckbox && !$canOnlyLengthenExpiry;
928 $irreversible = !$disabledCheckbox && (
929 ( $set && !$this->canAdd( $group ) ) ||
930 ( !$set && !$this->canRemove( $group ) ) );
934 'disabled' => $disabledCheckbox,
935 'disabled-expiry' => $disabledExpiry,
936 'irreversible' => $irreversible
939 if ( $disabledCheckbox && $disabledExpiry ) {
940 $columns[
'unchangeable'][$group] = $checkbox;
942 $columns[
'changeable'][$group] = $checkbox;
947 $ret .=
Xml::openElement(
'table', [
'class' =>
'mw-userrights-groups' ] ) .
949 foreach ( $columns as $name => $column ) {
950 if ( $column === [] ) {
957 $this->
msg(
'userrights-' . $name .
'-col', count( $column ) )->text()
961 $ret .=
"</tr>\n<tr>\n";
964 foreach ( $columns as $column ) {
965 if ( $column === [] ) {
968 $ret .=
"\t<td style='vertical-align:top;'>\n";
969 foreach ( $column as $group => $checkbox ) {
970 $member = $uiLanguage->getGroupMemberName( $group, $userName );
971 if ( $checkbox[
'irreversible'] ) {
972 $text = $this->
msg(
'userrights-irreversible-marker', $member )->text();
973 } elseif ( $checkbox[
'disabled'] && !$checkbox[
'disabled-expiry'] ) {
974 $text = $this->
msg(
'userrights-no-shorten-expiry-marker', $member )->text();
979 'type' =>
'checkbox',
'name' =>
"wpGroup-$group",
'value' =>
'1',
980 'id' =>
"wpGroup-$group",
'checked' => $checkbox[
'set'],
981 'class' =>
'mw-userrights-groupcheckbox',
982 'disabled' => $checkbox[
'disabled'],
983 ] ) .
' ' . Html::label( $text,
"wpGroup-$group" );
988 $currentExpiry = isset( $usergroups[$group] ) ?
989 $usergroups[$group]->getExpiry() :
994 if ( $checkbox[
'set'] &&
995 ( $checkbox[
'irreversible'] || $checkbox[
'disabled-expiry'] )
997 if ( $currentExpiry ) {
998 $expiryFormatted = $uiLanguage->userTimeAndDate( $currentExpiry, $uiUser );
999 $expiryFormattedD = $uiLanguage->userDate( $currentExpiry, $uiUser );
1000 $expiryFormattedT = $uiLanguage->userTime( $currentExpiry, $uiUser );
1002 $this->
msg(
'userrights-expiry-current' )->params(
1003 $expiryFormatted, $expiryFormattedD, $expiryFormattedT )->text() );
1006 $this->
msg(
'userrights-expiry-none' )->text() );
1010 $expiryHtml .= Html::hidden(
"wpExpiry-$group",
1011 $currentExpiry ?
'existing' :
'infinite' );
1012 $expiryHtml .=
"<br />\n";
1015 $this->
msg(
'userrights-expiry' )->text() );
1016 $expiryHtml .= Html::openElement(
'span' );
1019 $expiryFormOptions =
new XmlSelect(
1021 "mw-input-wpExpiry-$group",
1022 $currentExpiry ?
'existing' :
'infinite'
1024 if ( $checkbox[
'disabled-expiry'] ) {
1025 $expiryFormOptions->setAttribute(
'disabled',
'disabled' );
1028 if ( $currentExpiry ) {
1029 $timestamp = $uiLanguage->userTimeAndDate( $currentExpiry, $uiUser );
1030 $d = $uiLanguage->userDate( $currentExpiry, $uiUser );
1031 $t = $uiLanguage->userTime( $currentExpiry, $uiUser );
1032 $existingExpiryMessage = $this->
msg(
'userrights-expiry-existing',
1033 $timestamp, $d, $t );
1034 $expiryFormOptions->addOption( $existingExpiryMessage->text(),
'existing' );
1037 $expiryFormOptions->addOption(
1038 $this->
msg(
'userrights-expiry-none' )->text(),
1041 $expiryFormOptions->addOption(
1042 $this->
msg(
'userrights-expiry-othertime' )->text(),
1046 $expiryFormOptions->addOptions( $expiryOptions );
1049 $expiryHtml .= $expiryFormOptions->getHTML() .
'<br />';
1053 'name' =>
"wpExpiry-$group-other",
'size' => 30,
'value' =>
'',
1054 'id' =>
"mw-input-wpExpiry-$group-other",
1055 'class' =>
'mw-userrights-expiryfield',
1056 'disabled' => $checkbox[
'disabled-expiry'],
1061 if ( $checkbox[
'set'] && $checkbox[
'disabled'] ) {
1062 $expiryHtml .= Html::hidden(
"wpGroup-$group", 1 );
1065 $expiryHtml .= Html::closeElement(
'span' );
1069 'id' =>
"mw-userrights-nested-wpGroup-$group",
1070 'class' =>
'mw-userrights-nested',
1072 $checkboxHtml .=
"\t\t\t" . Html::rawElement(
'div', $divAttribs, $expiryHtml ) .
"\n";
1074 $ret .=
"\t\t" . ( ( $checkbox[
'disabled'] && $checkbox[
'disabled-expiry'] )
1075 ? Html::rawElement(
'div', [
'class' =>
'mw-userrights-disabled' ], $checkboxHtml )
1076 : Html::rawElement(
'div', [], $checkboxHtml )
1079 $ret .=
"\t</td>\n";
1081 $ret .= Html::closeElement(
'tr' ) . Html::closeElement(
'table' );
1083 return [ $ret, (bool)$columns[
'changeable'] ];
1090 private function canRemove( $group ) {
1095 $groups[
'remove'] ) || ( $this->isself && in_array( $group, $groups[
'remove-self'] )
1103 private function canAdd( $group ) {
1108 $groups[
'add'] ) || ( $this->isself && in_array( $group, $groups[
'add-self'] )
1133 private function getDisplayUsername(
UserIdentity $user ) {
1135 if ( $user->
getWikiId() !== UserIdentity::LOCAL ) {
1149 $rightsLogPage =
new LogPage(
'rights' );
1150 $output->addHTML(
Html::element(
'h2', [], $rightsLogPage->getName()->text() ) );
1151 LogEventsList::showLogExtract( $output,
'rights',
1152 Title::makeTitle(
NS_USER, $this->getDisplayUsername( $user ) ) );
1164 $search = $this->userNameUtils->getCanonical( $search );
1170 return $this->userNamePrefixSearch
1171 ->search( UserNamePrefixSearch::AUDIENCE_PUBLIC, $search, $limit, $offset );
1183class_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 By default the message key is the canonical name of...
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.
Interface for database access objects.