* $wgSQLiteDataDirMode has been introduced as the default directory mode for
SQLite data directories on creation. Note this setting is separate from
$wgDirectoryMode, which applies to all normal directories created by MediaWiki.
-
+* $wgGroupsAddToSelf and $wgGroupsRemoveFromSelf now work more like
+ $wgAddGroups and $wgRemoveGroups, where the user must belong to a specified
+ group in order to add or remove those groups from themselves.
+ Backwards compatibility is maintained.
+
=== New features in 1.14 ===
* New URL syntaxes for Special:ListUsers - 'Special:ListUsers/USER' and
option enabled on Special:ProtectedPages
* (bug 15157) Special:Watchlist has the same options as Special:Watchlist:
Show/Hide logged in users, Show/Hide anonymous, Invert namespace selection
-
+* Added hook 'UserrightsChangeableGroups' to allow modification of what
+ groups may be added or removed via the Special:UserRights interface.
+
=== Bug fixes in 1.14 ===
* (bug 14907) DatabasePostgres::fieldType now defined.
// Validate input set...
$changeable = $this->changeableGroups();
- if ($wgUser->getId() != 0 && $wgUser->getId() == $user->getId()) {
- $addable = array_merge($changeable['add'], $wgGroupsAddToSelf);
- $removable = array_merge($changeable['remove'], $wgGroupsRemoveFromSelf);
- } else {
- $addable = $changeable['add'];
- $removable = $changeable['remove'];
- }
+ $addable = array_merge( $changeable['add'], $this->isself ? $changeable['add-self'] : array() );
+ $removable = array_merge( $changeable['remove'], $this->isself ? $changeable['remove-self'] : array() );
$removegroup = array_unique(
array_intersect( (array)$removegroup, $removable ) );
* @return Array: Tuple of addable, then removable groups
*/
protected function splitGroups( $groups ) {
- global $wgGroupsAddToSelf, $wgGroupsRemoveFromSelf;
- list($addable, $removable) = array_values( $this->changeableGroups() );
+ list($addable, $removable, $addself, $removeself) = array_values( $this->changeableGroups() );
$removable = array_intersect(
- array_merge($this->isself ? $wgGroupsRemoveFromSelf : array(), $removable),
+ array_merge( $this->isself ? $removeself : array(), $removable ),
$groups ); // Can't remove groups the user doesn't have
$addable = array_diff(
- array_merge($this->isself ? $wgGroupsAddToSelf : array(), $addable),
+ array_merge( $this->isself ? $addself : array(), $addable ),
$groups ); // Can't add groups the user does have
return array( $addable, $removable );
/**
* Returns an array of the groups that the user can add/remove.
*
- * @return Array array( 'add' => array( addablegroups ), 'remove' => array( removablegroups ) )
+ * @return Array array( 'add' => array( addablegroups ), 'remove' => array( removablegroups ) , 'add-self' => array( addablegroups to self), 'remove-self' => array( removable groups from self) )
*/
function changeableGroups() {
- global $wgUser, $wgGroupsAddToSelf, $wgGroupsRemoveFromSelf;
+ global $wgUser;
if( $wgUser->isAllowed( 'userrights' ) ) {
// This group gives the right to modify everything (reverse-
$groups = array(
'add' => array(),
'remove' => array(),
- 'add-self' => $wgGroupsAddToSelf,
- 'remove-self' => $wgGroupsRemoveFromSelf);
+ 'add-self' => array(),
+ 'remove-self' => array() );
$addergroups = $wgUser->getEffectiveGroups();
foreach ($addergroups as $addergroup) {
);
$groups['add'] = array_unique( $groups['add'] );
$groups['remove'] = array_unique( $groups['remove'] );
+ $groups['add-self'] = array_unique( $groups['add-self'] );
+ $groups['remove-self'] = array_unique( $groups['remove-self'] );
}
+
+ // Run a hook because we can
+ wfRunHooks( 'UserrightsChangeableGroups', array( $this, $wgUser, $addergroups, &$groups ) );
+
return $groups;
}
* Returns an array of the groups that a particular group can add/remove.
*
* @param $group String: the group to check for whether it can add/remove
- * @return Array array( 'add' => array( addablegroups ), 'remove' => array( removablegroups ) )
+ * @return Array array( 'add' => array( addablegroups ), 'remove' => array( removablegroups ) , 'add-self' => array( addablegroups to self), 'remove-self' => array( removable groups from self) )
*/
private function changeableByGroup( $group ) {
- global $wgAddGroups, $wgRemoveGroups;
+ global $wgAddGroups, $wgRemoveGroups, $wgGroupsAddToSelf, $wgGroupsRemoveFromSelf;
- $groups = array( 'add' => array(), 'remove' => array() );
+ $groups = array( 'add' => array(), 'remove' => array(), 'add-self' => array(), 'remove-self' => array() );
if( empty($wgAddGroups[$group]) ) {
// Don't add anything to $groups
} elseif( $wgAddGroups[$group] === true ) {
} elseif( is_array($wgRemoveGroups[$group]) ) {
$groups['remove'] = $wgRemoveGroups[$group];
}
+
+ // Re-map numeric keys of AddToSelf/RemoveFromSelf to the 'user' key for backwards compatibility
+ if( empty($wgGroupsAddToSelf['user']) || $wgGroupsAddToSelf['user'] !== true ) {
+ foreach($wgGroupsAddToSelf as $key => $value) {
+ if( is_int($key) ) {
+ $wgGroupsAddToSelf['user'][] = $value;
+ }
+ }
+ }
+
+ if( empty($wgGroupsRemoveFromSelf['user']) || $wgGroupsRemoveFromSelf['user'] !== true ) {
+ foreach($wgGroupsRemoveFromSelf as $key => $value) {
+ if( is_int($key) ) {
+ $wgGroupsRemoveFromSelf['user'][] = $value;
+ }
+ }
+ }
+
+ // Now figure out what groups the user can add to him/herself
+ if( empty($wgGroupsAddToSelf[$group]) ) {
+ } elseif( $wgGroupsAddToSelf[$group] === true ) {
+ // No idea WHY this would be used, but it's there
+ $groups['add-self'] = User::getAllGroups();
+ } elseif( is_array($wgGroupsAddToSelf[$group]) ) {
+ $groups['add-self'] = $wgGroupsAddToSelf[$group];
+ }
+
+ if( empty($wgGroupsRemoveFromSelf[$group]) ) {
+ } elseif( $wgGroupsRemoveFromSelf[$group] === true ) {
+ $groups['remove-self'] = User::getAllGroups();
+ } elseif( is_array($wgGroupsRemoveFromSelf[$group]) ) {
+ $groups['remove-self'] = $wgGroupsRemoveFromSelf[$group];
+ }
+
return $groups;
}