MediaWiki master
SpecialListGroupRights.php
Go to the documentation of this file.
1<?php
21namespace MediaWiki\Specials;
22
35
45
46 private NamespaceInfo $nsInfo;
47 private UserGroupManager $userGroupManager;
48 private ILanguageConverter $languageConverter;
49 private GroupPermissionsLookup $groupPermissionsLookup;
50
51 public function __construct(
52 NamespaceInfo $nsInfo,
53 UserGroupManager $userGroupManager,
54 LanguageConverterFactory $languageConverterFactory,
55 GroupPermissionsLookup $groupPermissionsLookup
56 ) {
57 parent::__construct( 'Listgrouprights' );
58 $this->nsInfo = $nsInfo;
59 $this->userGroupManager = $userGroupManager;
60 $this->languageConverter = $languageConverterFactory->getLanguageConverter( $this->getContentLanguage() );
61 $this->groupPermissionsLookup = $groupPermissionsLookup;
62 }
63
68 public function execute( $par ) {
69 $this->setHeaders();
70 $this->outputHeader();
71
72 $out = $this->getOutput();
73 $out->addModuleStyles( 'mediawiki.special' );
74 $this->addHelpLink( 'Help:User_rights_and_groups' );
75
76 $out->wrapWikiMsg( "<div class=\"mw-listgrouprights-key\">\n$1\n</div>", 'listgrouprights-key' );
77
78 $out->addHTML(
79 Html::openElement( 'table', [ 'class' => [ 'wikitable', 'mw-listgrouprights-table' ] ] ) .
80 '<tr>' .
81 Html::element( 'th', [], $this->msg( 'listgrouprights-group' )->text() ) .
82 Html::element( 'th', [], $this->msg( 'listgrouprights-rights' )->text() ) .
83 '</tr>'
84 );
85
86 $config = $this->getConfig();
87 $addGroups = $config->get( MainConfigNames::AddGroups );
88 $removeGroups = $config->get( MainConfigNames::RemoveGroups );
89 $groupsAddToSelf = $config->get( MainConfigNames::GroupsAddToSelf );
90 $groupsRemoveFromSelf = $config->get( MainConfigNames::GroupsRemoveFromSelf );
91 $allGroups = array_merge(
92 $this->userGroupManager->listAllGroups(),
93 $this->userGroupManager->listAllImplicitGroups()
94 );
95 asort( $allGroups );
96
97 $linkRenderer = $this->getLinkRenderer();
98 $lang = $this->getLanguage();
99
100 foreach ( $allGroups as $group ) {
101 $permissions = $this->groupPermissionsLookup->getGrantedPermissions( $group );
102 $groupname = ( $group == '*' ) // Replace * with a more descriptive groupname
103 ? 'all'
104 : $group;
105
106 $groupnameLocalized = $lang->getGroupName( $groupname );
107
108 $grouppageLocalizedTitle = UserGroupMembership::getGroupPage( $groupname )
109 ?: Title::makeTitleSafe( NS_PROJECT, $groupname );
110
111 if ( $group == '*' || !$grouppageLocalizedTitle ) {
112 // Do not make a link for the generic * group or group with invalid group page
113 $grouppage = htmlspecialchars( $groupnameLocalized );
114 } else {
115 $grouppage = $linkRenderer->makeLink(
116 $grouppageLocalizedTitle,
117 $groupnameLocalized
118 );
119 }
120
121 $groupWithParentheses = $this->msg( 'parentheses' )->rawParams( $group )->escaped();
122 $groupname = "<br /><code>$groupWithParentheses</code>";
123
124 if ( $group === 'user' ) {
125 // Link to Special:listusers for implicit group 'user'
126 $grouplink = '<br />' . $linkRenderer->makeKnownLink(
127 SpecialPage::getTitleFor( 'Listusers' ),
128 $this->msg( 'listgrouprights-members' )->text()
129 );
130 } elseif ( !in_array( $group, $config->get( MainConfigNames::ImplicitGroups ) ) ) {
131 $grouplink = '<br />' . $linkRenderer->makeKnownLink(
132 SpecialPage::getTitleFor( 'Listusers' ),
133 $this->msg( 'listgrouprights-members' )->text(),
134 [],
135 [ 'group' => $group ]
136 );
137 } else {
138 // No link to Special:listusers for other implicit groups as they are unlistable
139 $grouplink = '';
140 }
141
142 $revoke = $this->groupPermissionsLookup->getRevokedPermissions( $group );
143 $addgroups = $addGroups[$group] ?? [];
144 $removegroups = $removeGroups[$group] ?? [];
145 $addgroupsSelf = $groupsAddToSelf[$group] ?? [];
146 $removegroupsSelf = $groupsRemoveFromSelf[$group] ?? [];
147
148 $id = $group == '*' ? false : Sanitizer::escapeIdForAttribute( $group );
149 $out->addHTML( Html::rawElement( 'tr', [ 'id' => $id ], "
150 <td>$grouppage$groupname$grouplink</td>
151 <td>" .
152 $this->formatPermissions( $permissions, $revoke, $addgroups, $removegroups,
153 $addgroupsSelf, $removegroupsSelf ) .
154 '</td>
155 '
156 ) );
157 }
158 $out->addHTML( Html::closeElement( 'table' ) );
159 $this->outputNamespaceProtectionInfo();
160 }
161
162 private function outputNamespaceProtectionInfo() {
163 $out = $this->getOutput();
164 $namespaceProtection = $this->getConfig()->get( MainConfigNames::NamespaceProtection );
165
166 if ( count( $namespaceProtection ) == 0 ) {
167 return;
168 }
169
170 $header = $this->msg( 'listgrouprights-namespaceprotection-header' )->text();
171 $out->addHTML(
172 Html::element( 'h2', [
173 'id' => Sanitizer::escapeIdForAttribute( $header )
174 ], $header ) .
175 Html::openElement( 'table', [ 'class' => 'wikitable' ] ) .
177 'th',
178 [],
179 $this->msg( 'listgrouprights-namespaceprotection-namespace' )->text()
180 ) .
182 'th',
183 [],
184 $this->msg( 'listgrouprights-namespaceprotection-restrictedto' )->text()
185 )
186 );
187 $linkRenderer = $this->getLinkRenderer();
188 ksort( $namespaceProtection );
189 $validNamespaces = $this->nsInfo->getValidNamespaces();
190 foreach ( $namespaceProtection as $namespace => $rights ) {
191 if ( !in_array( $namespace, $validNamespaces ) ) {
192 continue;
193 }
194
195 if ( $namespace == NS_MAIN ) {
196 $namespaceText = $this->msg( 'blanknamespace' )->text();
197 } else {
198 $namespaceText = $this->languageConverter->convertNamespace( $namespace );
199 }
200
201 $out->addHTML(
202 Html::openElement( 'tr' ) .
203 Html::rawElement(
204 'td',
205 [],
206 $linkRenderer->makeLink(
207 SpecialPage::getTitleFor( 'Allpages' ),
208 $namespaceText,
209 [],
210 [ 'namespace' => $namespace ]
211 )
212 ) .
213 Html::openElement( 'td' ) . Html::openElement( 'ul' )
214 );
215
216 if ( !is_array( $rights ) ) {
217 $rights = [ $rights ];
218 }
219
220 foreach ( $rights as $right ) {
221 $out->addHTML( Html::rawElement( 'li', [],
222 $this->msg( 'listgrouprights-right-display' )
223 ->params( User::getRightDescription( $right ) )
224 ->rawParams( Html::element(
225 'span',
226 [ 'class' => 'mw-listgrouprights-right-name' ],
227 $right
228 ) )->parse()
229 ) );
230 }
231
232 $out->addHTML(
233 Html::closeElement( 'ul' ) .
234 Html::closeElement( 'td' ) .
235 Html::closeElement( 'tr' )
236 );
237 }
238 $out->addHTML( Html::closeElement( 'table' ) );
239 }
240
252 private function formatPermissions( $permissions, $revoke, $add, $remove, $addSelf, $removeSelf ) {
253 $r = [];
254 foreach ( $permissions as $permission ) {
255 // show as granted only if it isn't revoked to prevent duplicate display of permissions
256 if ( !isset( $revoke[$permission] ) || !$revoke[$permission] ) {
257 $r[] = $this->msg( 'listgrouprights-right-display' )
258 ->params( User::getRightDescription( $permission ) )
259 ->rawParams( Html::element(
260 'span',
261 [ 'class' => 'mw-listgrouprights-right-name' ],
262 $permission
263 ) )->parse();
264 }
265 }
266 foreach ( $revoke as $permission ) {
267 $r[] = $this->msg( 'listgrouprights-right-revoked' )
268 ->params( User::getRightDescription( $permission ) )
269 ->rawParams( Html::element(
270 'span',
271 [ 'class' => 'mw-listgrouprights-right-name' ],
272 $permission
273 ) )->parse();
274 }
275
276 sort( $r );
277
278 $lang = $this->getLanguage();
279 $allGroups = $this->userGroupManager->listAllGroups();
280
281 $changeGroups = [
282 'addgroup' => $add,
283 'removegroup' => $remove,
284 'addgroup-self' => $addSelf,
285 'removegroup-self' => $removeSelf
286 ];
287
288 foreach ( $changeGroups as $messageKey => $changeGroup ) {
289 // @phan-suppress-next-line PhanTypeComparisonFromArray
290 if ( $changeGroup === true ) {
291 // For grep: listgrouprights-addgroup-all, listgrouprights-removegroup-all,
292 // listgrouprights-addgroup-self-all, listgrouprights-removegroup-self-all
293 $r[] = $this->msg( 'listgrouprights-' . $messageKey . '-all' )->escaped();
294 } elseif ( is_array( $changeGroup ) ) {
295 $changeGroup = array_intersect( array_values( array_unique( $changeGroup ) ), $allGroups );
296 if ( count( $changeGroup ) ) {
297 $groupLinks = [];
298 foreach ( $changeGroup as $group ) {
299 $groupLinks[] = UserGroupMembership::getLinkWiki( $group, $this->getContext() );
300 }
301 // For grep: listgrouprights-addgroup, listgrouprights-removegroup,
302 // listgrouprights-addgroup-self, listgrouprights-removegroup-self
303 $r[] = $this->msg( 'listgrouprights-' . $messageKey,
304 $lang->listToText( $groupLinks ), count( $changeGroup ) )->parse();
305 }
306 }
307 }
308
309 if ( !$r ) {
310 return '';
311 } else {
312 return '<ul><li>' . implode( "</li>\n<li>", $r ) . '</li></ul>';
313 }
314 }
315
316 protected function getGroupName() {
317 return 'users';
318 }
319}
320
322class_alias( SpecialListGroupRights::class, 'SpecialListGroupRights' );
const NS_MAIN
Definition Defines.php:65
const NS_PROJECT
Definition Defines.php:69
This class is a collection of static functions that serve two purposes:
Definition Html.php:57
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 By default the message key is the canonical name of...
addHelpLink( $to, $overrideBaseUrl=false)
Adds help link with an icon via page indicators.
List 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
Manage user group memberships.
Represents the membership of one user in one user group.
User class for the MediaWiki software.
Definition User.php:123
The shared interface for all language converters.
element(SerializerNode $parent, SerializerNode $node, $contents)