Page Menu
Home
WickedGov Phorge
Search
Configure Global Search
Log In
Files
F2750480
SpecialGlobalGroupMembership.php
No One
Temporary
Actions
Download File
Edit File
Delete File
View Transforms
Subscribe
Flag For Later
Award Token
Size
22 KB
Referenced Files
None
Subscribers
None
SpecialGlobalGroupMembership.php
View Options
<?php
/**
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
* http://www.gnu.org/copyleft/gpl.html
*
* @file
*/
namespace
MediaWiki\Extension\CentralAuth\Special
;
use
LogEventsList
;
use
LogPage
;
use
ManualLogEntry
;
use
MediaWiki\CommentStore\CommentStore
;
use
MediaWiki\Extension\CentralAuth\GlobalGroup\GlobalGroupLookup
;
use
MediaWiki\Extension\CentralAuth\User\CentralAuthUser
;
use
MediaWiki\Extension\CentralAuth\Widget\HTMLGlobalUserTextField
;
use
MediaWiki\Html\Html
;
use
MediaWiki\HTMLForm\HTMLForm
;
use
MediaWiki\Linker\Linker
;
use
MediaWiki\Output\OutputPage
;
use
MediaWiki\SpecialPage\SpecialPage
;
use
MediaWiki\Specials\SpecialUserRights
;
use
MediaWiki\Status\Status
;
use
MediaWiki\Title\TitleFactory
;
use
MediaWiki\User\UserGroupMembership
;
use
MediaWiki\User\UserNamePrefixSearch
;
use
MediaWiki\User\UserNameUtils
;
use
MediaWiki\Xml\Xml
;
use
MediaWiki\Xml\XmlSelect
;
use
PermissionsError
;
use
UserBlockedError
;
/**
* Equivalent of Special:Userrights for global groups.
*
* @ingroup Extensions
*/
class
SpecialGlobalGroupMembership
extends
SpecialPage
{
/**
* The target of the local right-adjuster's interest. Can be gotten from
* either a GET parameter or a subpage-style parameter, so have a member
* variable for it.
* @var null|string
*/
protected
$mTarget
;
/**
* @var null|CentralAuthUser The user object of the target username or null.
*/
protected
$mFetchedUser
=
null
;
private
TitleFactory
$titleFactory
;
private
UserNamePrefixSearch
$userNamePrefixSearch
;
private
UserNameUtils
$userNameUtils
;
private
GlobalGroupLookup
$globalGroupLookup
;
public
function
__construct
(
TitleFactory
$titleFactory
,
UserNamePrefixSearch
$userNamePrefixSearch
,
UserNameUtils
$userNameUtils
,
GlobalGroupLookup
$globalGroupLookup
)
{
parent
::
__construct
(
'GlobalGroupMembership'
);
$this
->
titleFactory
=
$titleFactory
;
$this
->
userNamePrefixSearch
=
$userNamePrefixSearch
;
$this
->
userNameUtils
=
$userNameUtils
;
$this
->
globalGroupLookup
=
$globalGroupLookup
;
}
/**
* @inheritDoc
*/
public
function
doesWrites
()
{
return
true
;
}
/**
* Manage forms to be shown according to posted data.
* Depending on the submit button used, call a form or a save function.
*
* @param string|null $par String if any subpage provided, else null
* @throws UserBlockedError|PermissionsError
*/
public
function
execute
(
$par
)
{
$user
=
$this
->
getUser
();
$request
=
$this
->
getRequest
();
$session
=
$request
->
getSession
();
$out
=
$this
->
getOutput
();
$out
->
addModules
(
[
'mediawiki.special.userrights'
]
);
$this
->
mTarget
=
$par
??
$request
->
getVal
(
'user'
);
$fetchedStatus
=
$this
->
mTarget
===
null
?
Status
::
newFatal
(
'nouserspecified'
)
:
$this
->
fetchUser
(
$this
->
mTarget
);
if
(
$fetchedStatus
->
isOK
()
)
{
$this
->
mFetchedUser
=
$fetchedStatus
->
value
;
}
// show a successbox, if the user rights was saved successfully
if
(
$session
->
get
(
'specialUserrightsSaveSuccess'
)
&&
$this
->
mFetchedUser
!==
null
)
{
// Remove session data for the success message
$session
->
remove
(
'specialUserrightsSaveSuccess'
);
$out
->
addModuleStyles
(
'mediawiki.notification.convertmessagebox.styles'
);
$out
->
addHTML
(
Html
::
successBox
(
Html
::
element
(
'p'
,
[],
$this
->
msg
(
'savedrights'
,
$this
->
mFetchedUser
->
getName
()
)->
text
()
),
'mw-notify-success'
)
);
}
$this
->
setHeaders
();
$this
->
outputHeader
();
$out
->
addModuleStyles
(
'mediawiki.special'
);
$this
->
addHelpLink
(
'Help:Assigning permissions'
);
$this
->
switchForm
();
if
(
$request
->
wasPosted
()
&&
$request
->
getCheck
(
'saveusergroups'
)
&&
$this
->
mTarget
!==
null
&&
$user
->
matchEditToken
(
$request
->
getVal
(
'wpEditToken'
),
$this
->
mTarget
)
)
{
/*
* If the user is blocked and they only have "partial" access
* (e.g. they don't have the userrights permission), then don't
* allow them to change any user rights.
*/
if
(
!
$this
->
getAuthority
()->
isAllowed
(
'userrights'
)
)
{
$block
=
$user
->
getBlock
();
if
(
$block
&&
$block
->
isSitewide
()
)
{
throw
new
UserBlockedError
(
$block
,
$user
,
$this
->
getLanguage
(),
$request
->
getIP
()
);
}
}
$this
->
checkReadOnly
();
// save settings
if
(
!
$fetchedStatus
->
isOK
()
)
{
$this
->
getOutput
()->
addWikiTextAsInterface
(
$fetchedStatus
->
getWikiText
(
false
,
false
,
$this
->
getLanguage
()
)
);
return
;
}
$targetUser
=
$this
->
mFetchedUser
;
$conflictCheck
=
$request
->
getVal
(
'conflictcheck-originalgroups'
);
$conflictCheck
=
(
$conflictCheck
===
''
)
?
[]
:
explode
(
','
,
$conflictCheck
);
$userGroups
=
$targetUser
->
getGlobalGroups
();
if
(
$userGroups
!==
$conflictCheck
)
{
$out
->
addHTML
(
Html
::
errorBox
(
$this
->
msg
(
'userrights-conflict'
)->
parse
()
)
);
}
else
{
$status
=
$this
->
saveUserGroups
(
$targetUser
,
$request
->
getVal
(
'user-reason'
)
);
if
(
$status
->
isOK
()
)
{
// Set session data for the success message
$session
->
set
(
'specialUserrightsSaveSuccess'
,
1
);
$out
->
redirect
(
$this
->
getSuccessURL
()
);
return
;
}
else
{
// Print an error message and redisplay the form
$out
->
wrapWikiTextAsInterface
(
'error'
,
$status
->
getWikiText
(
false
,
false
,
$this
->
getLanguage
()
)
);
}
}
}
// show some more forms
if
(
$this
->
mTarget
!==
null
)
{
$this
->
editUserGroupsForm
(
$this
->
mTarget
);
}
}
/**
* @return string
*/
private
function
getSuccessURL
()
{
return
$this
->
getPageTitle
(
$this
->
mTarget
)->
getFullURL
();
}
/**
* Save user groups changes in the database.
* Data comes from the editUserGroupsForm() form function
*
* @param CentralAuthUser $user Target user object.
* @param string $reason Reason for group change
* @return Status
*/
private
function
saveUserGroups
(
CentralAuthUser
$user
,
string
$reason
):
Status
{
$allgroups
=
$this
->
globalGroupLookup
->
getDefinedGroups
();
$addgroup
=
[];
// associative array of (group name => expiry)
$groupExpiries
=
[];
$removegroup
=
[];
$existingGroups
=
$user
->
getGlobalGroupsWithExpiration
();
// This could possibly create a highly unlikely race condition if permissions are changed between
// when the form is loaded and when the form is saved. Ignoring it for the moment.
foreach
(
$allgroups
as
$group
)
{
// We'll tell it to remove all unchecked groups, and add all checked groups.
// Later on, this gets filtered for what can actually be removed
if
(
$this
->
getRequest
()->
getCheck
(
"wpGroup-$group"
)
)
{
$addgroup
[]
=
$group
;
// read the expiry information from the request
$expiryDropdown
=
$this
->
getRequest
()->
getVal
(
"wpExpiry-$group"
);
if
(
$expiryDropdown
===
'existing'
)
{
continue
;
}
if
(
$expiryDropdown
===
'other'
)
{
$expiryValue
=
$this
->
getRequest
()->
getVal
(
"wpExpiry-$group-other"
);
}
else
{
$expiryValue
=
$expiryDropdown
;
}
// validate the expiry
$groupExpiries
[
$group
]
=
SpecialUserRights
::
expiryToTimestamp
(
$expiryValue
);
if
(
$groupExpiries
[
$group
]
===
false
)
{
return
Status
::
newFatal
(
'userrights-invalid-expiry'
,
$group
);
}
// not allowed to have things expiring in the past
if
(
$groupExpiries
[
$group
]
&&
$groupExpiries
[
$group
]
<
wfTimestampNow
()
)
{
return
Status
::
newFatal
(
'userrights-expiry-in-past'
,
$group
);
}
}
else
{
$removegroup
[]
=
$group
;
}
}
$this
->
doSaveUserGroups
(
$user
,
$addgroup
,
$removegroup
,
$reason
,
[],
$groupExpiries
);
return
Status
::
newGood
();
}
/**
* Save user groups changes in the database. This function does not throw errors;
* instead, it ignores groups that the performer does not have permission to set.
*
* @param CentralAuthUser $user
* @param string[] $add Array of groups to add
* @param string[] $remove Array of groups to remove
* @param string $reason Reason for group change
* @param string[] $tags Array of change tags to add to the log entry
* @param array<string,?string> $groupExpiries Associative array of (group name => expiry),
* containing only those groups that are to have new expiry values set
* @return array Tuple of added, then removed groups
*/
public
function
doSaveUserGroups
(
CentralAuthUser
$user
,
array
$add
,
array
$remove
,
string
$reason
=
''
,
array
$tags
=
[],
array
$groupExpiries
=
[]
)
{
// Validate input set...
$groups
=
$user
->
getGlobalGroupsWithExpiration
();
$changeable
=
$this
->
changeableGroups
();
$remove
=
array_unique
(
array_intersect
(
$remove
,
$changeable
,
array_keys
(
$groups
)
)
);
$add
=
array_intersect
(
$add
,
$changeable
);
// add only groups that are not already present or that need their expiry updated
$add
=
array_filter
(
$add
,
static
function
(
$group
)
use
(
$groups
,
$groupExpiries
)
{
return
!
array_key_exists
(
$group
,
$groups
)
||
array_key_exists
(
$group
,
$groupExpiries
);
}
);
// Remove groups, then add new ones/update expiries of existing ones
if
(
$remove
)
{
foreach
(
$remove
as
$group
)
{
$user
->
removeFromGlobalGroups
(
$group
);
}
}
if
(
$add
)
{
foreach
(
$add
as
$group
)
{
$expiry
=
$groupExpiries
[
$group
]
??
null
;
$user
->
addToGlobalGroup
(
$group
,
$expiry
);
}
}
$newGroups
=
$user
->
getGlobalGroupsWithExpiration
();
// Ensure that caches are cleared
$user
->
invalidateCache
();
// Only add a log entry if something actually changed
if
(
$groups
!==
$newGroups
)
{
$this
->
addLogEntry
(
$user
,
$groups
,
$newGroups
,
$reason
,
$tags
);
}
return
[
$add
,
$remove
];
}
/**
* @param CentralAuthUser $user
* @param array $oldGroups
* @param array $newGroups
* @param string $reason
* @param array $tags Not currently used
*/
private
function
addLogEntry
(
CentralAuthUser
$user
,
array
$oldGroups
,
array
$newGroups
,
string
$reason
,
array
$tags
)
{
$oldGroupNames
=
[];
$newGroupNames
=
[];
$oldGroupMetadata
=
[];
$newGroupMetadata
=
[];
foreach
(
$oldGroups
as
$key
=>
&
$value
)
{
$oldGroupNames
[]
=
$key
;
$oldGroupMetadata
[]
=
[
'expiry'
=>
$value
];
}
foreach
(
$newGroups
as
$key
=>
&
$value
)
{
$newGroupNames
[]
=
$key
;
$newGroupMetadata
[]
=
[
'expiry'
=>
$value
];
}
$entry
=
new
ManualLogEntry
(
'gblrights'
,
'usergroups'
);
$entry
->
setTarget
(
$this
->
titleFactory
->
makeTitle
(
NS_USER
,
$user
->
getName
()
)
);
$entry
->
setPerformer
(
$this
->
getUser
()
);
$entry
->
setComment
(
$reason
);
$entry
->
setParameters
(
[
'oldGroups'
=>
$oldGroupNames
,
'newGroups'
=>
$newGroupNames
,
'oldMetadata'
=>
$oldGroupMetadata
,
'newMetadata'
=>
$newGroupMetadata
,
]
);
$logid
=
$entry
->
insert
();
$entry
->
publish
(
$logid
);
}
/**
* Edit user groups membership
* @param string $username Name of the user.
*/
private
function
editUserGroupsForm
(
$username
)
{
$status
=
$this
->
fetchUser
(
$username
);
if
(
!
$status
->
isOK
()
)
{
$this
->
getOutput
()->
addWikiTextAsInterface
(
$status
->
getWikiText
(
false
,
false
,
$this
->
getLanguage
()
)
);
return
;
}
/** @var CentralAuthUser $user */
$user
=
$status
->
value
;
'@phan-var CentralAuthUser $user'
;
$this
->
showEditUserGroupsForm
(
$user
);
// This isn't really ideal logging behavior, but let's not hide the
// interwiki logs if we're using them as is.
$this
->
showLogFragment
(
$user
,
$this
->
getOutput
()
);
}
/**
* @param string $username
* @return Status
*/
public
function
fetchUser
(
$username
)
{
if
(
$username
===
''
)
{
return
Status
::
newFatal
(
'nouserspecified'
);
}
if
(
$username
[
0
]
==
'#'
)
{
$id
=
intval
(
substr
(
$username
,
1
)
);
$globalUser
=
CentralAuthUser
::
newPrimaryInstanceFromId
(
$id
);
// If the user exists, but is hidden from the viewer, pretend that it does
// not exist. - T285190/T260863
if
(
!
$globalUser
||
(
(
$globalUser
->
isSuppressed
()
||
$globalUser
->
isHidden
()
)
&&
!
$this
->
getContext
()->
getAuthority
()->
isAllowed
(
'centralauth-suppress'
)
)
)
{
return
Status
::
newFatal
(
'noname'
,
$id
);
}
}
else
{
// fetchUser() is public; normalize in case the caller forgot to. See T343963 and
// T344495.
$username
=
$this
->
userNameUtils
->
getCanonical
(
$username
);
if
(
!
is_string
(
$username
)
)
{
// $username was invalid, return nosuchuser.
return
Status
::
newFatal
(
'nosuchusershort'
,
$username
);
}
// If the user exists, but is hidden from the viewer, pretend that it does
// not exist. - T285190
$globalUser
=
CentralAuthUser
::
getPrimaryInstanceByName
(
$username
);
if
(
!
$globalUser
->
exists
()
||
(
(
$globalUser
->
isSuppressed
()
||
$globalUser
->
isHidden
()
)
&&
!
$this
->
getContext
()->
getAuthority
()->
isAllowed
(
'centralauth-suppress'
)
)
)
{
return
Status
::
newFatal
(
'nosuchusershort'
,
$username
);
}
}
return
Status
::
newGood
(
$globalUser
);
}
/**
* Output a form to allow searching for a user
*/
private
function
switchForm
()
{
$this
->
addHelpLink
(
'Extension:CentralAuth'
);
$this
->
getOutput
()->
addModuleStyles
(
'mediawiki.special'
);
$formDescriptor
=
[
'user'
=>
[
'class'
=>
HTMLGlobalUserTextField
::
class
,
'name'
=>
'user'
,
'id'
=>
'username'
,
'label-message'
=>
'userrights-user-editname'
,
'size'
=>
30
,
'default'
=>
$this
->
mTarget
,
]
];
$htmlForm
=
HTMLForm
::
factory
(
'ooui'
,
$formDescriptor
,
$this
->
getContext
()
);
$htmlForm
->
setMethod
(
'get'
)
// Strip subpage
->
setTitle
(
$this
->
getPageTitle
()
)
->
setAction
(
$this
->
getConfig
()->
get
(
'Script'
)
)
->
setId
(
'mw-userrights-form1'
)
->
setName
(
'uluser'
)
->
setSubmitTextMsg
(
'editusergroup'
)
->
setWrapperLegendMsg
(
'userrights-lookup-user'
)
->
prepareForm
()
->
displayForm
(
false
);
}
/**
* Show the form to edit group memberships.
* @param CentralAuthUser $user user you're editing
*/
private
function
showEditUserGroupsForm
(
CentralAuthUser
$user
)
{
$list
=
$membersList
=
$tempList
=
$tempMembersList
=
[];
foreach
(
$user
->
getGlobalGroupsWithExpiration
()
as
$group
=>
$expiration
)
{
$ugm
=
new
UserGroupMembership
(
$user
->
getId
(),
$group
,
$expiration
);
$linkG
=
UserGroupMembership
::
getLinkHTML
(
$ugm
,
$this
->
getContext
()
);
$linkM
=
UserGroupMembership
::
getLinkHTML
(
$ugm
,
$this
->
getContext
(),
$user
->
getName
()
);
if
(
$ugm
->
getExpiry
()
)
{
$tempList
[]
=
$linkG
;
$tempMembersList
[]
=
$linkM
;
}
else
{
$list
[]
=
$linkG
;
$membersList
[]
=
$linkM
;
}
}
$language
=
$this
->
getLanguage
();
$displayedList
=
$this
->
msg
(
'userrights-groupsmember-type'
)
->
rawParams
(
$language
->
commaList
(
array_merge
(
$tempList
,
$list
)
),
$language
->
commaList
(
array_merge
(
$tempMembersList
,
$membersList
)
)
)->
escaped
();
$grouplist
=
''
;
$count
=
count
(
$list
)
+
count
(
$tempList
);
if
(
$count
>
0
)
{
$grouplist
=
$this
->
msg
(
'userrights-groupsmember'
)
->
numParams
(
$count
)
->
params
(
$user
->
getName
()
)
->
parse
();
$grouplist
=
'<p>'
.
$grouplist
.
' '
.
$displayedList
.
"</p>
\n
"
;
}
$userToolLinks
=
Linker
::
userToolLinks
(
$user
->
getId
(),
$user
->
getName
(),
// default for redContribsWhenNoEdits
false
,
Linker
::
TOOL_LINKS_EMAIL
);
$canChangeAny
=
$this
->
changeableGroups
()
!==
[];
$this
->
getOutput
()->
addHTML
(
Xml
::
openElement
(
'form'
,
[
'method'
=>
'post'
,
'action'
=>
$this
->
getPageTitle
()->
getLocalURL
(),
'name'
=>
'editGroup'
,
'id'
=>
'mw-userrights-form2'
]
)
.
Html
::
hidden
(
'user'
,
$this
->
mTarget
)
.
Html
::
hidden
(
'wpEditToken'
,
$this
->
getUser
()->
getEditToken
(
$this
->
mTarget
)
)
.
// Conflict detection
Html
::
hidden
(
'conflictcheck-originalgroups'
,
implode
(
','
,
$user
->
getGlobalGroups
()
)
)
.
Xml
::
openElement
(
'fieldset'
)
.
Xml
::
element
(
'legend'
,
[],
$this
->
msg
(
$canChangeAny
?
'userrights-editusergroup'
:
'userrights-viewusergroup'
,
$user
->
getName
()
)->
text
()
)
.
$this
->
msg
(
$canChangeAny
?
'editinguser'
:
'viewinguserrights'
)->
params
(
wfEscapeWikiText
(
$user
->
getName
()
)
)
->
rawParams
(
$userToolLinks
)->
parse
()
);
if
(
$canChangeAny
)
{
$this
->
getOutput
()->
addHTML
(
$this
->
msg
(
'userrights-groups-help'
,
$user
->
getName
()
)->
parse
()
.
$grouplist
.
$this
->
groupCheckboxes
(
$user
)
.
Xml
::
openElement
(
'table'
,
[
'id'
=>
'mw-userrights-table-outer'
]
)
.
"<tr>
<td class='mw-label'>"
.
Xml
::
label
(
$this
->
msg
(
'userrights-reason'
)->
text
(),
'wpReason'
)
.
"</td>
<td class='mw-input'>"
.
Xml
::
input
(
'user-reason'
,
60
,
$this
->
getRequest
()->
getVal
(
'user-reason'
)
??
false
,
[
'id'
=>
'wpReason'
,
// HTML maxlength uses "UTF-16 code units", which means that characters outside BMP
// (e.g. emojis) count for two each. This limit is overridden in JS to instead count
// Unicode codepoints.
'maxlength'
=>
CommentStore
::
COMMENT_CHARACTER_LIMIT
,
]
)
.
"</td>
</tr>
<tr>
<td></td>
<td class='mw-submit'>"
.
Xml
::
submitButton
(
$this
->
msg
(
'saveusergroups'
,
$user
->
getName
()
)->
text
(),
[
'name'
=>
'saveusergroups'
]
+
Linker
::
tooltipAndAccesskeyAttribs
(
'userrights-set'
)
)
.
"</td>
</tr>"
.
Xml
::
closeElement
(
'table'
)
.
"
\n
"
);
}
else
{
$this
->
getOutput
()->
addHTML
(
$grouplist
);
}
$this
->
getOutput
()->
addHTML
(
Xml
::
closeElement
(
'fieldset'
)
.
Xml
::
closeElement
(
'form'
)
.
"
\n
"
);
}
/**
* Adds a table with checkboxes where you can select what groups to add/remove.
*
* This is only called when the user can change any of the groups.
*
* @param CentralAuthUser $user
* @return string The HTML table element with checkboxes and expiry dropdowns
*/
private
function
groupCheckboxes
(
CentralAuthUser
$user
)
{
$allgroups
=
$this
->
globalGroupLookup
->
getDefinedGroups
();
$currentGroups
=
$user
->
getGlobalGroupsWithExpiration
();
$ret
=
''
;
// Get the list of preset expiry times from the system message
$expiryOptionsMsg
=
$this
->
msg
(
'userrights-expiry-options'
)->
inContentLanguage
();
$expiryOptions
=
$expiryOptionsMsg
->
isDisabled
()
?
[]
:
XmlSelect
::
parseOptionsMessage
(
$expiryOptionsMsg
->
text
()
);
// Build the HTML table
$ret
.=
Xml
::
openElement
(
'table'
,
[
'class'
=>
'mw-userrights-groups'
]
)
.
"<tr>
\n
"
;
$ret
.=
Xml
::
element
(
'th'
,
null
,
$this
->
msg
(
'userrights-changeable-col'
,
count
(
$allgroups
)
)->
text
()
);
$ret
.=
"</tr>
\n
<tr>
\n
"
;
$uiLanguage
=
$this
->
getLanguage
();
$ret
.=
"
\t
<td style='vertical-align:top;'>
\n
"
;
foreach
(
$allgroups
as
$group
)
{
$set
=
array_key_exists
(
$group
,
$currentGroups
);
$member
=
$uiLanguage
->
getGroupMemberName
(
$group
,
$user
->
getName
()
);
$id
=
"wpGroup-$group"
;
$checkboxHtml
=
Html
::
element
(
'input'
,
[
'class'
=>
'mw-userrights-groupcheckbox'
,
'type'
=>
'checkbox'
,
'value'
=>
'1'
,
'checked'
=>
$set
,
'id'
=>
$id
,
'name'
=>
$id
,
]
)
.
' '
.
Html
::
label
(
$member
,
$id
);
$uiUser
=
$this
->
getUser
();
$currentExpiry
=
$currentGroups
[
$group
]
??
null
;
$expiryHtml
=
Xml
::
element
(
'span'
,
null
,
$this
->
msg
(
'userrights-expiry'
)->
text
()
);
$expiryHtml
.=
Xml
::
openElement
(
'span'
);
// add a form element to set the expiry date
$expiryFormOptions
=
new
XmlSelect
(
"wpExpiry-$group"
,
// forward compatibility with HTMLForm
"mw-input-wpExpiry-$group"
,
$currentExpiry
?
'existing'
:
'infinite'
);
if
(
$currentExpiry
)
{
$timestamp
=
$uiLanguage
->
userTimeAndDate
(
$currentExpiry
,
$uiUser
);
$d
=
$uiLanguage
->
userDate
(
$currentExpiry
,
$uiUser
);
$t
=
$uiLanguage
->
userTime
(
$currentExpiry
,
$uiUser
);
$existingExpiryMessage
=
$this
->
msg
(
'userrights-expiry-existing'
,
$timestamp
,
$d
,
$t
);
$expiryFormOptions
->
addOption
(
$existingExpiryMessage
->
text
(),
'existing'
);
}
$expiryFormOptions
->
addOption
(
$this
->
msg
(
'userrights-expiry-none'
)->
text
(),
'infinite'
);
$expiryFormOptions
->
addOption
(
$this
->
msg
(
'userrights-expiry-othertime'
)->
text
(),
'other'
);
$expiryFormOptions
->
addOptions
(
$expiryOptions
);
// Add expiry dropdown
$expiryHtml
.=
$expiryFormOptions
->
getHTML
()
.
'<br />'
;
// Add custom expiry field
$attribs
=
[
'id'
=>
"mw-input-wpExpiry-$group-other"
,
'class'
=>
'mw-userrights-expiryfield'
,
];
$expiryHtml
.=
Xml
::
input
(
"wpExpiry-$group-other"
,
30
,
''
,
$attribs
);
$expiryHtml
.=
Xml
::
closeElement
(
'span'
);
$divAttribs
=
[
'id'
=>
"mw-userrights-nested-wpGroup-$group"
,
'class'
=>
'mw-userrights-nested'
,
];
$checkboxHtml
.=
"
\t\t\t
"
.
Xml
::
tags
(
'div'
,
$divAttribs
,
$expiryHtml
)
.
"
\n
"
;
$ret
.=
"
\t\t
"
.
Xml
::
tags
(
'div'
,
[],
$checkboxHtml
)
.
"
\n
"
;
}
$ret
.=
"
\t
</td>
\n
"
;
$ret
.=
Xml
::
closeElement
(
'tr'
)
.
Xml
::
closeElement
(
'table'
);
return
$ret
;
}
/**
* @return string[]
*/
private
function
changeableGroups
()
{
if
(
$this
->
getContext
()->
getAuthority
()->
isAllowed
(
'globalgroupmembership'
)
)
{
return
$this
->
globalGroupLookup
->
getDefinedGroups
();
}
return
[];
}
/**
* @param CentralAuthUser $user
* @param OutputPage $output
*/
private
function
showLogFragment
(
$user
,
$output
)
{
$logPage
=
new
LogPage
(
'gblrights'
);
$output
->
addHTML
(
Xml
::
element
(
'h2'
,
null
,
$logPage
->
getName
()->
text
()
.
"
\n
"
)
);
LogEventsList
::
showLogExtract
(
$output
,
'gblrights'
,
$this
->
titleFactory
->
makeTitle
(
NS_USER
,
$user
->
getName
()
)
);
}
/**
* Return an array of subpages beginning with $search that this special page will accept.
*
* @param string $search Prefix to search for
* @param int $limit Maximum number of results to return (usually 10)
* @param int $offset Number of results to skip (usually 0)
* @return string[] Matching subpages
*/
public
function
prefixSearchSubpages
(
$search
,
$limit
,
$offset
)
{
$search
=
$this
->
userNameUtils
->
getCanonical
(
$search
);
if
(
!
$search
)
{
// No prefix suggestion for invalid user
return
[];
}
// Autocomplete subpage as user list - public to allow caching
return
$this
->
userNamePrefixSearch
->
search
(
UserNamePrefixSearch
::
AUDIENCE_PUBLIC
,
$search
,
$limit
,
$offset
);
}
/**
* @inheritDoc
*/
protected
function
getGroupName
()
{
return
'users'
;
}
}
File Metadata
Details
Attached
Mime Type
text/x-php
Expires
Fri, Jul 3, 16:34 (8 h, 58 m)
Storage Engine
local-disk
Storage Format
Raw Data
Storage Handle
63/4d/5a27a5f31a350ea68835beed6bbc
Default Alt Text
SpecialGlobalGroupMembership.php (22 KB)
Attached To
Mode
rMWPROD MediaWiki Production
Attached
Detach File
Event Timeline
Log In to Comment