MediaWiki master
SpecialListGroupRights.php
Go to the documentation of this file.
1<?php
24namespace MediaWiki\Specials;
25
38
47
48 private NamespaceInfo $nsInfo;
49 private UserGroupManager $userGroupManager;
50 private ILanguageConverter $languageConverter;
51 private GroupPermissionsLookup $groupPermissionsLookup;
52
59 public function __construct(
60 NamespaceInfo $nsInfo,
61 UserGroupManager $userGroupManager,
62 LanguageConverterFactory $languageConverterFactory,
63 GroupPermissionsLookup $groupPermissionsLookup
64 ) {
65 parent::__construct( 'Listgrouprights' );
66 $this->nsInfo = $nsInfo;
67 $this->userGroupManager = $userGroupManager;
68 $this->languageConverter = $languageConverterFactory->getLanguageConverter( $this->getContentLanguage() );
69 $this->groupPermissionsLookup = $groupPermissionsLookup;
70 }
71
76 public function execute( $par ) {
77 $this->setHeaders();
78 $this->outputHeader();
79
80 $out = $this->getOutput();
81 $out->addModuleStyles( 'mediawiki.special' );
82 $this->addHelpLink( 'Help:User_rights_and_groups' );
83
84 $out->wrapWikiMsg( "<div class=\"mw-listgrouprights-key\">\n$1\n</div>", 'listgrouprights-key' );
85
86 $out->addHTML(
87 Html::openElement( 'table', [ 'class' => 'wikitable mw-listgrouprights-table' ] ) .
88 '<tr>' .
89 Html::element( 'th', [], $this->msg( 'listgrouprights-group' )->text() ) .
90 Html::element( 'th', [], $this->msg( 'listgrouprights-rights' )->text() ) .
91 '</tr>'
92 );
93
94 $config = $this->getConfig();
95 $addGroups = $config->get( MainConfigNames::AddGroups );
96 $removeGroups = $config->get( MainConfigNames::RemoveGroups );
97 $groupsAddToSelf = $config->get( MainConfigNames::GroupsAddToSelf );
98 $groupsRemoveFromSelf = $config->get( MainConfigNames::GroupsRemoveFromSelf );
99 $allGroups = array_merge(
100 $this->userGroupManager->listAllGroups(),
101 $this->userGroupManager->listAllImplicitGroups()
102 );
103 asort( $allGroups );
104
105 $linkRenderer = $this->getLinkRenderer();
106 $lang = $this->getLanguage();
107
108 foreach ( $allGroups as $group ) {
109 $permissions = $this->groupPermissionsLookup->getGrantedPermissions( $group );
110 $groupname = ( $group == '*' ) // Replace * with a more descriptive groupname
111 ? 'all'
112 : $group;
113
114 $groupnameLocalized = $lang->getGroupName( $groupname );
115
116 $grouppageLocalizedTitle = UserGroupMembership::getGroupPage( $groupname )
117 ?: Title::makeTitleSafe( NS_PROJECT, $groupname );
118
119 if ( $group == '*' || !$grouppageLocalizedTitle ) {
120 // Do not make a link for the generic * group or group with invalid group page
121 $grouppage = htmlspecialchars( $groupnameLocalized );
122 } else {
123 $grouppage = $linkRenderer->makeLink(
124 $grouppageLocalizedTitle,
125 $groupnameLocalized
126 );
127 }
128
129 $groupWithParentheses = $this->msg( 'parentheses' )->rawParams( $group )->escaped();
130 $groupname = "<br /><code>$groupWithParentheses</code>";
131
132 if ( $group === 'user' ) {
133 // Link to Special:listusers for implicit group 'user'
134 $grouplink = '<br />' . $linkRenderer->makeKnownLink(
135 SpecialPage::getTitleFor( 'Listusers' ),
136 $this->msg( 'listgrouprights-members' )->text()
137 );
138 } elseif ( !in_array( $group, $config->get( MainConfigNames::ImplicitGroups ) ) ) {
139 $grouplink = '<br />' . $linkRenderer->makeKnownLink(
140 SpecialPage::getTitleFor( 'Listusers' ),
141 $this->msg( 'listgrouprights-members' )->text(),
142 [],
143 [ 'group' => $group ]
144 );
145 } else {
146 // No link to Special:listusers for other implicit groups as they are unlistable
147 $grouplink = '';
148 }
149
150 $revoke = $this->groupPermissionsLookup->getRevokedPermissions( $group );
151 $addgroups = $addGroups[$group] ?? [];
152 $removegroups = $removeGroups[$group] ?? [];
153 $addgroupsSelf = $groupsAddToSelf[$group] ?? [];
154 $removegroupsSelf = $groupsRemoveFromSelf[$group] ?? [];
155
156 $id = $group == '*' ? false : Sanitizer::escapeIdForAttribute( $group );
157 $out->addHTML( Html::rawElement( 'tr', [ 'id' => $id ], "
158 <td>$grouppage$groupname$grouplink</td>
159 <td>" .
160 $this->formatPermissions( $permissions, $revoke, $addgroups, $removegroups,
161 $addgroupsSelf, $removegroupsSelf ) .
162 '</td>
163 '
164 ) );
165 }
166 $out->addHTML( Html::closeElement( 'table' ) );
167 $this->outputNamespaceProtectionInfo();
168 }
169
170 private function outputNamespaceProtectionInfo() {
171 $out = $this->getOutput();
172 $namespaceProtection = $this->getConfig()->get( MainConfigNames::NamespaceProtection );
173
174 if ( count( $namespaceProtection ) == 0 ) {
175 return;
176 }
177
178 $header = $this->msg( 'listgrouprights-namespaceprotection-header' )->text();
179 $out->addHTML(
180 Html::element( 'h2', [
181 'id' => Sanitizer::escapeIdForAttribute( $header )
182 ], $header ) .
183 Html::openElement( 'table', [ 'class' => 'wikitable' ] ) .
185 'th',
186 [],
187 $this->msg( 'listgrouprights-namespaceprotection-namespace' )->text()
188 ) .
190 'th',
191 [],
192 $this->msg( 'listgrouprights-namespaceprotection-restrictedto' )->text()
193 )
194 );
195 $linkRenderer = $this->getLinkRenderer();
196 ksort( $namespaceProtection );
197 $validNamespaces = $this->nsInfo->getValidNamespaces();
198 foreach ( $namespaceProtection as $namespace => $rights ) {
199 if ( !in_array( $namespace, $validNamespaces ) ) {
200 continue;
201 }
202
203 if ( $namespace == NS_MAIN ) {
204 $namespaceText = $this->msg( 'blanknamespace' )->text();
205 } else {
206 $namespaceText = $this->languageConverter->convertNamespace( $namespace );
207 }
208
209 $out->addHTML(
210 Html::openElement( 'tr' ) .
211 Html::rawElement(
212 'td',
213 [],
214 $linkRenderer->makeLink(
215 SpecialPage::getTitleFor( 'Allpages' ),
216 $namespaceText,
217 [],
218 [ 'namespace' => $namespace ]
219 )
220 ) .
221 Html::openElement( 'td' ) . Html::openElement( 'ul' )
222 );
223
224 if ( !is_array( $rights ) ) {
225 $rights = [ $rights ];
226 }
227
228 foreach ( $rights as $right ) {
229 $out->addHTML( Html::rawElement( 'li', [],
230 $this->msg( 'listgrouprights-right-display' )
231 ->params( User::getRightDescription( $right ) )
232 ->rawParams( Html::element(
233 'span',
234 [ 'class' => 'mw-listgrouprights-right-name' ],
235 $right
236 ) )->parse()
237 ) );
238 }
239
240 $out->addHTML(
241 Html::closeElement( 'ul' ) .
242 Html::closeElement( 'td' ) .
243 Html::closeElement( 'tr' )
244 );
245 }
246 $out->addHTML( Html::closeElement( 'table' ) );
247 }
248
260 private function formatPermissions( $permissions, $revoke, $add, $remove, $addSelf, $removeSelf ) {
261 $r = [];
262 foreach ( $permissions as $permission ) {
263 // show as granted only if it isn't revoked to prevent duplicate display of permissions
264 if ( !isset( $revoke[$permission] ) || !$revoke[$permission] ) {
265 $r[] = $this->msg( 'listgrouprights-right-display' )
266 ->params( User::getRightDescription( $permission ) )
267 ->rawParams( Html::element(
268 'span',
269 [ 'class' => 'mw-listgrouprights-right-name' ],
270 $permission
271 ) )->parse();
272 }
273 }
274 foreach ( $revoke as $permission ) {
275 $r[] = $this->msg( 'listgrouprights-right-revoked' )
276 ->params( User::getRightDescription( $permission ) )
277 ->rawParams( Html::element(
278 'span',
279 [ 'class' => 'mw-listgrouprights-right-name' ],
280 $permission
281 ) )->parse();
282 }
283
284 sort( $r );
285
286 $lang = $this->getLanguage();
287 $allGroups = $this->userGroupManager->listAllGroups();
288
289 $changeGroups = [
290 'addgroup' => $add,
291 'removegroup' => $remove,
292 'addgroup-self' => $addSelf,
293 'removegroup-self' => $removeSelf
294 ];
295
296 foreach ( $changeGroups as $messageKey => $changeGroup ) {
297 // @phan-suppress-next-line PhanTypeComparisonFromArray
298 if ( $changeGroup === true ) {
299 // For grep: listgrouprights-addgroup-all, listgrouprights-removegroup-all,
300 // listgrouprights-addgroup-self-all, listgrouprights-removegroup-self-all
301 $r[] = $this->msg( 'listgrouprights-' . $messageKey . '-all' )->escaped();
302 } elseif ( is_array( $changeGroup ) ) {
303 $changeGroup = array_intersect( array_values( array_unique( $changeGroup ) ), $allGroups );
304 if ( count( $changeGroup ) ) {
305 $groupLinks = [];
306 foreach ( $changeGroup as $group ) {
307 $groupLinks[] = UserGroupMembership::getLinkWiki( $group, $this->getContext() );
308 }
309 // For grep: listgrouprights-addgroup, listgrouprights-removegroup,
310 // listgrouprights-addgroup-self, listgrouprights-removegroup-self
311 $r[] = $this->msg( 'listgrouprights-' . $messageKey,
312 $lang->listToText( $groupLinks ), count( $changeGroup ) )->parse();
313 }
314 }
315 }
316
317 if ( !$r ) {
318 return '';
319 } else {
320 return '<ul><li>' . implode( "</li>\n<li>", $r ) . '</li></ul>';
321 }
322 }
323
324 protected function getGroupName() {
325 return 'users';
326 }
327}
328
330class_alias( SpecialListGroupRights::class, 'SpecialListGroupRights' );
const NS_MAIN
Definition Defines.php:64
const NS_PROJECT
Definition Defines.php:68
This class is a collection of static functions that serve two purposes:
Definition Html.php:56
An interface for creating language converters.
getLanguageConverter( $language=null)
Provide a LanguageConverter for given language.
A class containing constants representing the names of configuration variables.
const ImplicitGroups
Name constant for the ImplicitGroups setting, for use with Config::get()
const NamespaceProtection
Name constant for the NamespaceProtection setting, for use with Config::get()
const GroupsRemoveFromSelf
Name constant for the GroupsRemoveFromSelf setting, for use with Config::get()
const AddGroups
Name constant for the AddGroups setting, for use with Config::get()
const GroupsAddToSelf
Name constant for the GroupsAddToSelf setting, for use with Config::get()
const RemoveGroups
Name constant for the RemoveGroups setting, for use with Config::get()
HTML sanitizer for MediaWiki.
Definition Sanitizer.php:46
Parent class for all special pages.
setHeaders()
Sets headers - this should be called from the execute() method of all derived classes!
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,...
getConfig()
Shortcut to get main config object.
getContext()
Gets the context this SpecialPage is executed in.
msg( $key,... $params)
Wrapper around wfMessage that sets the current context.
getOutput()
Get the OutputPage being used for this instance.
getContentLanguage()
Shortcut to get content language.
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.
This special page lists all defined user groups and the associated rights.
getGroupName()
Under which header this special page is listed in Special:SpecialPages See messages 'specialpages-gro...
__construct(NamespaceInfo $nsInfo, UserGroupManager $userGroupManager, LanguageConverterFactory $languageConverterFactory, GroupPermissionsLookup $groupPermissionsLookup)
This is a utility class for dealing with namespaces that encodes all the "magic" behaviors of them ba...
Represents a title within MediaWiki.
Definition Title.php:78
Represents a "user group membership" – a specific instance of a user belonging to a group.
internal since 1.36
Definition User.php:93
The shared interface for all language converters.
element(SerializerNode $parent, SerializerNode $node, $contents)
This program is free software; you can redistribute it and/or modify it under the terms of the GNU Ge...
$header