MediaWiki r9367 - Code Review

Jump to: navigation, search
Repository:MediaWiki
Revision:r9366‎ | r9367 (on ViewVC)‎ | r9368 >
Date:09:49, 9 June 2005
Author:vibber
Status:old
Tags:
Comment:
Rework the user_groups system, again, into something that seems to actually
more or less work for now.

* user_groups ur_group is now a short string key ('sysop' etc)
* groups table is gone
* user_rights table is gone
* Permissions for groups are for now set in $wgGroupPermissions.
An in-database management system could be re-added in the future
if it's really needed, but for now it's mostly just been screwing
things up.
* Group.php and Special:Groups are deprecated; will probably die.
* User group memberships are set explicitly through addGroup and
removeGroup methods instead of being re-saved on every change to
the user record.

Group keys are migrated from user_rights at upgrade time for older wikis.
The fields in prior 1.5alpha tables were too screwed up and will need to
manually have sysops re-assigned.

The Makesysop extension will need some minor tweaks.
Modified paths:

Diff [purge]

Index: trunk/phase3/maintenance/archives/patch-user_groups.sql
===================================================================
--- trunk/phase3/maintenance/archives/patch-user_groups.sql	(revision 0)
+++ trunk/phase3/maintenance/archives/patch-user_groups.sql	(revision 9367)
@@ -0,0 +1,25 @@
+--
+-- User permissions have been broken out to a separate table;
+-- this allows sites with a shared user table to have different
+-- permissions assigned to a user in each project.
+--
+-- This table replaces the old user_rights field which used a
+-- comma-separated blob.
+--
+CREATE TABLE /*$wgDBprefix*/user_groups (
+  -- Key to user_id
+  ug_user int(5) unsigned NOT NULL default '0',
+  
+  -- Group names are short symbolic string keys.
+  -- The set of group names is open-ended, though in practice
+  -- only some predefined ones are likely to be used.
+  --
+  -- At runtime $wgGroupPermissions will associate group keys
+  -- with particular permissions. A user will have the combined
+  -- permissions of any group they're explicitly in, plus
+  -- the implicit '*' and 'user' groups.
+  ug_group char(16) NOT NULL default '',
+  
+  PRIMARY KEY (ug_user,ug_group),
+  KEY (ug_group)
+) TYPE=InnoDB;

Property changes on: trunk/phase3/maintenance/archives/patch-user_groups.sql
___________________________________________________________________
Name: svn:eol-style
   + native
Name: svn:keywords
   + Author Date Id Revision

Index: trunk/phase3/maintenance/parserTests.php
===================================================================
--- trunk/phase3/maintenance/parserTests.php	(revision 9366)
+++ trunk/phase3/maintenance/parserTests.php	(revision 9367)
@@ -327,7 +327,7 @@
 			'recentchanges',
 			'watchlist', 'math', 'searchindex',
 			'interwiki', 'querycache',
-			'objectcache', 'groups'
+			'objectcache'
 		);
 	}
 	
@@ -406,13 +406,6 @@
 				       'iw_local'  => 1 ),
 				) );
 
-			# Hack: initialize a group
-			$db->insert( 'groups', array(
-				'gr_id' => 1,
-				'gr_name' => 'Anonymous',
-				'gr_description' => 'Anonymous users',
-				'gr_rights' => 'read' ) );
-			
 			# Hack: Insert an image to work with
 			$db->insert( 'image', array(
 				'img_name'        => 'Foobar.jpg',
Index: trunk/phase3/maintenance/updaters.inc
===================================================================
--- trunk/phase3/maintenance/updaters.inc	(revision 9366)
+++ trunk/phase3/maintenance/updaters.inc	(revision 9367)
@@ -12,7 +12,7 @@
 
 $wgRenamedTables = array(
 #           from             to                  patch file
-	array( 'group',         'groups',           'patch-rename-group.sql' ),
+#	array( 'group',         'groups',           'patch-rename-group.sql' ),
 );
 
 $wgNewTables = array(
@@ -22,8 +22,6 @@
 	array( 'objectcache',   'patch-objectcache.sql' ),
 	array( 'categorylinks', 'patch-categorylinks.sql' ),
 	array( 'logging',       'patch-logging.sql' ),
-	array( 'user_rights',   'patch-user_rights.sql' ),
-	array( 'groups',        'patch-userlevels.sql' ),
 	array( 'validate',      'patch-validate.sql' ),
 );
 
@@ -38,8 +36,6 @@
 	array( 'user',          'user_real_name',   'patch-user-realname.sql' ),
 	array( 'user',          'user_token',       'patch-user_token.sql' ),
 	array( 'user',          'user_email_token', 'patch-user_email_token.sql' ),
-	array( 'user_rights',   'ur_user',          'patch-rename-user_groups-and_rights.sql' ),
-	array( 'groups',        'gr_rights',        'patch-userlevels-rights.sql' ),
  	array( 'logging',       'log_params',       'patch-log_params.sql' ),
  	array( 'archive',       'ar_rev_id',        'patch-archive-rev_id.sql' ),
  	array( 'archive',       'ar_text_id',       'patch-archive-text_id.sql' ),
@@ -238,20 +234,6 @@
 	}
 }
 
-# Assumes that the groups table has been added.
-function do_group_update() {
-	global $wgDatabase;
-	$res = $wgDatabase->safeQuery( 'SELECT COUNT(*) AS c FROM !',
-		$wgDatabase->tableName( 'groups' ) );
-	$row = $wgDatabase->fetchObject( $res );
-	$wgDatabase->freeResult( $res );
-	if( $row->c == 0 ) {
-		echo "Adding default group definitions... ";
-		dbsource( "maintenance/archives/patch-userlevels-defaultgroups.sql", $wgDatabase );
-		echo "ok\n";
-	}
-}
-
 /**
  * 1.4 betas were missing the 'binary' marker from logging.log_title,
  * which causes a collation mismatch error on joins in MySQL 4.1.
@@ -572,6 +554,81 @@
 	}
 }
 
+function do_user_groups_update() {
+	$fname = 'do_user_groups_update';
+	global $wgDatabase;
+	
+	if( $wgDatabase->tableExists( 'user_groups' ) ) {
+		echo "...user_groups table already exists.\n";
+		return do_user_groups_reformat();
+	}
+	
+	echo "Adding user_groups table... ";
+	dbsource( 'maintenance/archives/patch-user_groups.sql', $wgDatabase );
+	echo "ok\n";
+	
+	if( !$wgDatabase->tableExists( 'user_rights' ) ) {
+		if( $wgDatabase->fieldExists( 'user', 'user_rights' ) ) {
+			echo "Upgrading from a 1.3 or older database? Breaking out user_rights for conversion...";
+			dbsource( 'maintenance/archives/patch-user_rights.sql', $wgDatabase );
+			echo "ok\n";
+		} else {
+			echo "*** WARNING: couldn't locate user_rights table or field for upgrade.\n";
+			echo "*** You may need to manually configure some sysops by manipulating\n";
+			echo "*** the user_groups table.\n";
+			return;
+		}
+	}
+	
+	echo "Converting user_rights table to user_groups... ";
+	$result = $wgDatabase->select( 'user_rights',
+		array( 'ur_user', 'ur_rights' ),
+		array( "ur_rights != ''" ),
+		$fname );
+	
+	while( $row = $wgDatabase->fetchObject( $result ) ) {
+		$groups = array_unique(
+			array_map( 'trim',
+				explode( ',', $row->ur_rights ) ) );
+		
+		foreach( $groups as $group ) {
+			$wgDatabase->insert( 'user_groups',
+				array(
+					'ug_user'  => $row->ur_user,
+					'ug_group' => $group ),
+				$fname );
+		}
+	}
+	$wgDatabase->freeResult( $result );
+	echo "ok\n";
+}
+
+function do_user_groups_reformat() {
+	# Check for bogus formats from previous 1.5 alpha code.
+	global $wgDatabase;
+	$info = $wgDatabase->fieldInfo( 'user_groups', 'ug_group' );
+	
+	if( $info->type == 'int' ) {
+		$oldug = $wgDatabase->tableName( 'user_groups' );
+		$newug = $wgDatabase->tableName( 'user_groups_bogus' );
+		echo "user_groups is in bogus intermediate format. Renaming to $newug... ";
+		$wgDatabase->query( "ALTER TABLE $oldug RENAME TO $newug" );
+		echo "ok\n";
+		
+		echo "Re-adding fresh user_groups table... ";
+		dbsource( 'maintenance/archives/patch-user_groups.sql', $wgDatabase );
+		echo "ok\n";
+		
+		echo "***\n";
+		echo "*** WARNING: You will need to manually fix up user permissions in the user_groups\n";
+		echo "*** table. Old 1.5 alpha versions did some pretty funky stuff...\n";
+		echo "***\n";
+	} else {
+		echo "...user_groups is in current format.\n";
+	}
+	
+}
+
 function do_all_updates() {
 	global $wgNewTables, $wgNewFields, $wgRenamedTables;
 	
@@ -592,9 +649,6 @@
 		flush();
 	}
 	
-	# Add default group data
-	do_group_update(); flush();
-
 	# Do schema updates which require special handling
 	do_interwiki_update(); flush();
 	do_index_update(); flush();
@@ -615,6 +669,7 @@
 	do_drop_img_type(); flush();
 	
 	do_user_unique_update(); flush();
+	do_user_groups_update(); flush();
 	
 	initialiseMessages(); flush();
 }
Index: trunk/phase3/maintenance/tables.sql
===================================================================
--- trunk/phase3/maintenance/tables.sql	(revision 9366)
+++ trunk/phase3/maintenance/tables.sql	(revision 9367)
@@ -114,17 +114,25 @@
 -- this allows sites with a shared user table to have different
 -- permissions assigned to a user in each project.
 --
--- TODO: de-blob this; it should be a property table
+-- This table replaces the old user_rights field which used a
+-- comma-separated blob.
 --
-CREATE TABLE /*$wgDBprefix*/user_rights (
+CREATE TABLE /*$wgDBprefix*/user_groups (
   -- Key to user_id
-  ur_user int(5) unsigned NOT NULL,
+  ug_user int(5) unsigned NOT NULL default '0',
   
-  -- Comma-separated list of permission keys
-  ur_rights tinyblob NOT NULL default '',
+  -- Group names are short symbolic string keys.
+  -- The set of group names is open-ended, though in practice
+  -- only some predefined ones are likely to be used.
+  --
+  -- At runtime $wgGroupPermissions will associate group keys
+  -- with particular permissions. A user will have the combined
+  -- permissions of any group they're explicitly in, plus
+  -- the implicit '*' and 'user' groups.
+  ug_group char(16) NOT NULL default '',
   
-  UNIQUE KEY ur_user (ur_user)
-
+  PRIMARY KEY (ug_user,ug_group),
+  KEY (ug_group)
 ) TYPE=InnoDB;
 
 -- The following table is no longer needed with Enotif >= 2.00
@@ -795,19 +803,11 @@
 
 
 -- Hold group name and description
-CREATE TABLE /*$wgDBprefix*/groups (
-  gr_id int(5) unsigned NOT NULL auto_increment,
-  gr_name varchar(50) NOT NULL default '',
-  gr_description varchar(255) NOT NULL default '',
-  gr_rights tinyblob,
-  PRIMARY KEY  (gr_id)
-
-) TYPE=InnoDB;
-
--- Relation table between user and groups
-CREATE TABLE /*$wgDBprefix*/user_groups (
-	ug_user int(5) unsigned NOT NULL default '0',
-	ug_group int(5) unsigned NOT NULL default '0',
-	PRIMARY KEY  (ug_user,ug_group)
-
-) TYPE=InnoDB;
+--CREATE TABLE /*$wgDBprefix*/groups (
+--  gr_id int(5) unsigned NOT NULL auto_increment,
+--  gr_name varchar(50) NOT NULL default '',
+--  gr_description varchar(255) NOT NULL default '',
+--  gr_rights tinyblob,
+--  PRIMARY KEY  (gr_id)
+--
+--) TYPE=InnoDB;
Index: trunk/phase3/config/index.php
===================================================================
--- trunk/phase3/config/index.php	(revision 9366)
+++ trunk/phase3/config/index.php	(revision 9367)
@@ -565,7 +565,6 @@
 			print "<li>Creating tables...";
 			dbsource( "../maintenance/tables.sql", $wgDatabase );
 			dbsource( "../maintenance/interwiki.sql", $wgDatabase );
-			dbsource( "../maintenance/archives/patch-userlevels-defaultgroups.sql", $wgDatabase );
 			print " done.</li>\n";
 
 			print "<li>Initializing data...";
@@ -585,9 +584,10 @@
 				if ( 0 == $u->idForName() ) {
 					$u->addToDatabase();
 					$u->setPassword( $conf->getSysopPass() );
-					$u->addRight( "sysop" );
-					$u->addRight( "bureaucrat" );
 					$u->saveSettings();
+
+					$u->addGroup( "sysop" );
+					$u->addGroup( "bureaucrat" );
 					
 					print "<li>Created sysop account <tt>" .
 						htmlspecialchars( $conf->SysopName ) . "</tt>.</li>\n";
Index: trunk/phase3/includes/SpecialUserrights.php
===================================================================
--- trunk/phase3/includes/SpecialUserrights.php	(revision 9366)
+++ trunk/phase3/includes/SpecialUserrights.php	(revision 9367)
@@ -10,7 +10,6 @@
 
 /** */
 require_once('HTMLForm.php');
-require_once('Group.php');
 
 /** Entry point */
 function wfSpecialUserrights() {
@@ -73,12 +72,12 @@
 		$u = User::newFromName($username);
 
 		if(is_null($u)) {
-			$wgOut->addHTML('<p>'.wfMsg('nosuchusershort',$username).'</p>');
+			$wgOut->addWikiText( wfMsg( 'nosuchusershort', htmlspecialchars( $username ) ) );
 			return;
 		}
 
 		if($u->getID() == 0) {
-			$wgOut->addHTML('<p>'.wfMsg('nosuchusershort',$username).'</p>');
+			$wgOut->addWikiText( wfMsg( 'nosuchusershort', htmlspecialchars( $username ) ) );
 			return;
 		}		
 
@@ -93,10 +92,17 @@
 			$newGroups = array_merge($newGroups, $addgroup);
 		}
 		$newGroups = array_unique( $newGroups );
+		
+		wfDebug( 'oldGroups: ' . print_r( $oldGroups, true ) );
+		wfDebug( 'newGroups: ' . print_r( $newGroups, true ) );
 
 		// save groups in user object and database
-		$u->setGroups($newGroups);
-		$u->saveSettings();
+		foreach( $removegroup as $group ) {
+			$u->removeGroup( $group );
+		}
+		foreach( $addgroup as $group ) {
+			$u->addGroup( $group );
+		}
 
 		$log = new LogPage( 'rights' );
 		$log->addEntry( 'rights', Title::makeTitle( NS_USER, $u->getName() ), '', array( $this->makeGroupNameList( $oldGroups ),
@@ -104,15 +110,7 @@
 	}
 
 	function makeGroupNameList( $ids ) {
-		$s = '';
-		foreach( $ids as $id ) {
-			if ( $s != '' ) {
-				$s .= ', ';
-			}
-			$groupObj = Group::newFromId( $id );
-			$s .= $groupObj->getExpandedName();
-		}
-		return $s;
+		return implode( ', ', $ids );
 	}
 
 	/**
@@ -126,7 +124,10 @@
 		$wgOut->addHTML( "<form name=\"uluser\" action=\"$this->action\" method=\"post\">\n" );
 		$wgOut->addHTML( $this->fieldset( 'lookup-user',
 				$this->textbox( 'user-editname' ) .
-				'<input type="submit" name="ssearchuser" value="'.wfMsg('editusergroup').'" />'
+				wfElement( 'input', array(
+					'type'  => 'submit',
+					'name'  => 'ssearchuser',
+					'value' => wfMsg( 'editusergroup' ) ) )
 		));
 		$wgOut->addHTML( "</form>\n" );
 	}
@@ -139,30 +140,30 @@
 		global $wgOut;
 		
 		$user = User::newFromName($username);
-		$encUser = htmlspecialchars( $username );
-		if(is_null($user)) {
-			$wgOut->addHTML('<p>'.wfMsg('nosuchusershort', $encUser).'</p>');
+		if( is_null( $user ) || $user->getID() == 0 ) {
+			$wgOut->addWikiText( wfMsg( 'nosuchusershort', wfEscapeWikiText( $username ) ) );
 			return;
 		}
-
-		if($user->getID() == 0) {
-			$wgOut->addHTML('<p>'.wfMsg('nosuchusershort', $encUser).'</p>');
-			return;
-		}		
 		
 		$groups = $user->getGroups();
 
 		$wgOut->addHTML( "<form name=\"editGroup\" action=\"$this->action\" method=\"post\">\n".
-						 '<input type="hidden" name="user-editname" value="'.$encUser.'" />');
-		$wgOut->addHTML( $this->fieldset( 'editusergroup',
-			wfMsg('editing', $this->mRequest->getVal('user-editname')).".<br />\n" .
+			wfElement( 'input', array(
+				'type'  => 'hidden',
+				'name'  => 'user-editname',
+				'value' => $username ) ) .
+			$this->fieldset( 'editusergroup',
+			$wgOut->parse( wfMsg('editing', $username ) ) .
 			'<table border="0" align="center"><tr><td>'.
 			HTMLSelectGroups('member', $this->mName.'-groupsmember', $groups,true,6).
 			'</td><td>'.
 			HTMLSelectGroups('available', $this->mName.'-groupsavailable', $groups,true,6,true).
 			'</td></tr></table>'."\n".
-			'<p>'.wfMsg('userrights-groupshelp').'</p>'."\n".
-			'<input type="submit" name="saveusergroups" value="'.wfMsg('saveusergroups').'" />'
+			$wgOut->parse( wfMsg('userrights-groupshelp') ) .
+			wfElement( 'input', array(
+				'type'  => 'submit',
+				'name'  => 'saveusergroups',
+				'value' => wfMsg( 'saveusergroups' ) ) )
 			));
 		$wgOut->addHTML( "</form>\n" );
 	}
Index: trunk/phase3/includes/User.php
===================================================================
--- trunk/phase3/includes/User.php	(revision 9366)
+++ trunk/phase3/includes/User.php	(revision 9367)
@@ -9,7 +9,6 @@
  *
  */
 require_once( 'WatchedItem.php' );
-require_once( 'Group.php' );
 
 # Number of characters in user_token field
 define( 'USER_TOKEN_LENGTH', 32 );
@@ -32,9 +31,7 @@
 	var $mToken;
 	var $mRealName;
 	var $mHash;
-	/** Array of group id the user belong to */
 	var $mGroups;
-	/**#@-*/
 
 	/** Construct using User:loadDefaults() */
 	function User()	{
@@ -563,7 +560,7 @@
 	 * Load a user from the database
 	 */
 	function loadFromDatabase() {
-		global $wgCommandLineMode, $wgAnonGroupId, $wgLoggedInGroupId;
+		global $wgCommandLineMode;
 		$fname = "User::loadFromDatabase";
 		
 		# Counter-intuitive, breaks various things, use User::setLoaded() if you want to suppress 
@@ -577,15 +574,9 @@
 		$this->mId = IntVal( $this->mId );
 
 		/** Anonymous user */
-		if(!$this->mId) {
+		if( !$this->mId ) {
 			/** Get rights */
-			$anong = Group::newFromId($wgAnonGroupId);
-			if (!$anong) 
-				wfDebugDieBacktrace("Please update your database schema "
-					."and populate initial group data from "
-					."maintenance/archives patches");
-			$anong->loadFromDatabase();
-			$this->mRights = explode(',', $anong->getRights());
+			$this->mRights = $this->getGroupPermissions( array( '*' ) );
 			$this->mDataLoaded = true;
 			return;
 		} # the following stuff is for non-anonymous users only
@@ -607,31 +598,16 @@
 			$this->mTouched = wfTimestamp(TS_MW,$s->user_touched);
 			$this->mToken = $s->user_token;
 
-			// Get groups id
-			$res = $dbr->select( 'user_groups', array( 'ug_group' ), array( 'ug_user' => $this->mId ) );
-			
-			// add the default group for logged in user
-			$this->mGroups = array( $wgLoggedInGroupId );
-
-			while($group = $dbr->fetchRow($res)) {
-				if ( $group[0] != $wgLoggedInGroupId ) {
-					$this->mGroups[] = $group[0];
-				}
+			$res = $dbr->select( 'user_groups',
+				array( 'ug_group' ),
+				array( 'ug_user' => $this->mId ),
+				$fname );
+			$this->mGroups = array();
+			while( $row = $dbr->fetchObject( $res ) ) {
+				$this->mGroups[] = $row->ug_group;
 			}
-
-
-			$this->mRights = array();
-			// now we merge groups rights to get this user rights
-			foreach($this->mGroups as $aGroupId) {
-				$g = Group::newFromId($aGroupId);
-				$g->loadFromDatabase();
-				$this->mRights = array_merge($this->mRights, explode(',', $g->getRights()));
-			}
-			
-			// array merge duplicate rights which are part of several groups
-			$this->mRights = array_unique($this->mRights);
-			
-			$dbr->freeResult($res);
+			$effectiveGroups = array_merge( array( '*', 'user' ), $this->mGroups );
+			$this->mRights = $this->getGroupPermissions( $effectiveGroups );
 		}
 
 		$this->mDataLoaded = true;
@@ -830,24 +806,75 @@
 		$this->loadFromDatabase();
 		return $this->mRights;
 	}
-	
-	function addRight( $rname )	{
-		$this->loadFromDatabase();
-		array_push( $this->mRights, $rname );
-		$this->invalidateCache();
-	}
 
+	/**
+	 * Get the list of explicit group memberships this user has.
+	 * The implicit * and user groups are not included.
+	 * @return array of strings
+	 */
 	function getGroups() {
 		$this->loadFromDatabase();
 		return $this->mGroups;
 	}
 
-	function setGroups($groups) {
-		$this->loadFromDatabase();
-		$this->mGroups = $groups;
+	/**
+	 * Get the list of implicit group memberships this user has.
+	 * This includes all explicit groups, plus 'user' if logged in
+	 * and '*' for all accounts.
+	 * @return array of strings
+	 */
+	function getEffectiveGroups() {
+		$base = array( '*' );
+		if( $this->isLoggedIn() ) {
+			$base[] = 'user';
+		}
+		return array_merge( $base, $this->getGroups() );
+	}
+	
+	/**
+	 * Remove the user from the given group.
+	 * This takes immediate effect.
+	 * @string $group
+	 */
+	function addGroup( $group ) {
+		$dbw =& wfGetDB( DB_MASTER );
+		$dbw->insert( 'user_groups',
+			array(
+				'ug_user'  => $this->getID(),
+				'ug_group' => $group,
+			),
+			'User::addGroup',
+			array( 'IGNORE' ) );
+		
+		$this->mGroups = array_merge( $this->mGroups, array( $group ) );
+		$this->mRights = User::getGroupPermissions( $this->getEffectiveGroups() );
+		
 		$this->invalidateCache();
+		$this->saveSettings();
 	}
+	
+	/**
+	 * Remove the user from the given group.
+	 * This takes immediate effect.
+	 * @string $group
+	 */
+	function removeGroup( $group ) {
+		$dbw =& wfGetDB( DB_MASTER );
+		$dbw->delete( 'user_groups',
+			array(
+				'ug_user'  => $this->getID(),
+				'ug_group' => $group,
+			),
+			'User::removeGroup' );
+		
+		$this->mGroups = array_diff( $this->mGroups, array( $group ) );
+		$this->mRights = User::getGroupPermissions( $this->getEffectiveGroups() );
+		
+		$this->invalidateCache();
+		$this->saveSettings();
+	}
 
+
 	/**
 	 * A more legible check for non-anonymousness.
 	 * Returns true if the user is not an anonymous visitor.
@@ -1167,23 +1194,7 @@
 				'user_id' => $this->mId
 			), $fname
 		);
-		$dbw->set( 'user_rights', 'ur_rights', implode( ',', $this->mRights ),
-			'ur_user='. $this->mId, $fname ); 
 		$wgMemc->delete( "$wgDBname:user:id:$this->mId" );
-		
-		// delete old groups
-		$dbw->delete( 'user_groups', array( 'ug_user' => $this->mId), $fname);
-		
-		// save new ones
-		foreach ($this->mGroups as $group) {
-			$dbw->replace( 'user_groups',
-				array(array('ug_user','ug_group')),
-				array(
-					'ug_user' => $this->mId,
-					'ug_group' => $group
-				), $fname
-			);
-		}
 	}
 
 	
@@ -1226,21 +1237,6 @@
 			), $fname
 		);
 		$this->mId = $dbw->insertId();
-		$dbw->insert( 'user_rights',
-			array(
-				'ur_user' => $this->mId,
-				'ur_rights' => implode( ',', $this->mRights )
-			), $fname
-		);
-		
-		foreach ($this->mGroups as $group) {
-			$dbw->insert( 'user_groups',
-				array(
-					'ug_user' => $this->mId,
-					'ug_group' => $group
-				), $fname
-			);
-		}
 	}
 
 	function spreadBlock() {
@@ -1591,6 +1587,51 @@
 			return false;
 		return true;
 	}
+	
+	/**
+	 * @param array $groups list of groups
+	 * @return array list of permission key names for given groups combined
+	 * @static
+	 */
+	function getGroupPermissions( $groups ) {
+		global $wgGroupPermissions;
+		$rights = array();
+		foreach( $groups as $group ) {
+			if( isset( $wgGroupPermissions[$group] ) ) {
+				$rights = array_merge( $rights, $wgGroupPermissions[$group] );
+			}
+		}
+		return $rights;
+	}
+
+	/**
+	 * @param string $group key name
+	 * @return string localized descriptive name, if provided
+	 * @static
+	 */
+	function getGroupName( $group ) {
+		$key = "group-$group-name";
+		$name = wfMsg( $key );
+		if( $name == '' || $name == "&lt;$key&gt;" ) {
+			return $group;
+		} else {
+			return $name;
+		}
+	}
+	
+	/**
+	 * Return the set of defined explicit groups.
+	 * The * and 'user' groups are not included.
+	 * @return array
+	 * @static
+	 */
+	function getAllGroups() {
+		global $wgGroupPermissions;
+		return array_diff(
+			array_keys( $wgGroupPermissions ),
+			array( '*', 'user' ) );
+	}
+
 }
 
 ?>
Index: trunk/phase3/includes/HTMLForm.php
===================================================================
--- trunk/phase3/includes/HTMLForm.php	(revision 9366)
+++ trunk/phase3/includes/HTMLForm.php	(revision 9367)
@@ -120,26 +120,34 @@
  * @param boolean $reverse If true, multiple select will hide selected elements (default false).
 */
 function HTMLSelectGroups($selectname, $selectmsg, $selected=array(), $multiple=false, $size=6, $reverse=false) {
-	global $wgOut;
-	$groups =& Group::getAllGroups();
+	$groups = User::getAllGroups();
+	$out = htmlspecialchars( wfMsg( $selectmsg ) );
 	
-	$out = wfMsg($selectmsg);
-	$out .= '<select name="'.$selectname;
-	if($multiple) {	$out.='[]" multiple="multiple" size="'.$size; }
-	$out.= "\">\n";
+	if( $multiple ) {
+		$attribs = array(
+			'name'    => $selectname . '[]',
+			'multiple'=> 'multiple',
+			'size'    => $size );
+	} else {
+		$attribs = array( 'name' => $selectname );
+	}
+	$out .= wfElement( 'select', $attribs, null );
 	
-	foreach ( $groups as $id => $g ) {
-		if($multiple) {
+	foreach( $groups as $group ) {
+		$attribs = array( 'value' => $group );
+		if( $multiple ) {
 			// for multiple will only show the things we want
-			if(in_array($id, $selected) xor $reverse) { 
-				$out .= '<option value="'.$id.'">'.$wgOut->parse( $g->getExpandedName() )."</option>\n";
+			if( !in_array( $group, $selected ) xor $reverse ) {
+				continue;
 			}
 		} else {
-			$out .= '<option ';
-			if(in_array($id, $selected)) { $out .= 'selected="selected" '; }
-			$out .= 'value="'.$id.'">'.$wgOut->parse( $g->getExpandedName() )."</option>\n";
+			if( in_array( $group, $selected ) ) {
+				$attribs['selected'] = 'selected';
+			}
 		}
+		$out .= wfElement( 'option', $attribs, User::getGroupName( $group ) ) . "\n";
 	}
+
 	$out .= "</select>\n";
 	return $out;
 }
Index: trunk/phase3/includes/Title.php
===================================================================
--- trunk/phase3/includes/Title.php	(revision 9366)
+++ trunk/phase3/includes/Title.php	(revision 9367)
@@ -958,7 +958,7 @@
 			/** If anon users can create an account,
 			    they need to reach the login page first! */
 			if( $wgUser->isAllowed( 'createaccount' )
-			    && $this->mId == NS_SPECIAL
+			    && $this->getNamespace() == NS_SPECIAL
 			    && $this->getText() == 'Userlogin' ) {
 				return true;
 			}
Index: trunk/phase3/includes/SpecialStatistics.php
===================================================================
--- trunk/phase3/includes/SpecialStatistics.php	(revision 9366)
+++ trunk/phase3/includes/SpecialStatistics.php	(revision 9367)
@@ -13,7 +13,7 @@
 	$fname = 'wfSpecialStatistics';
 
 	$dbr =& wfGetDB( DB_SLAVE );
-	extract( $dbr->tableNames( 'page', 'site_stats', 'user', 'user_rights' ) );
+	extract( $dbr->tableNames( 'page', 'site_stats', 'user', 'user_groups' ) );
 
 	$sql = "SELECT COUNT(page_namespace) AS total FROM $page";
 	$res = $dbr->query( $sql, $fname );
@@ -44,7 +44,7 @@
 	$row = $dbr->fetchObject( $res );
 	$total = $row->total;
 
-	$sql = "SELECT COUNT(ur_user) AS total FROM $user_rights WHERE ur_rights LIKE '%sysop%'";
+	$sql = "SELECT COUNT(*) AS total FROM $user_groups WHERE ug_group='sysop'";
 	$res = $dbr->query( $sql, $fname );
 	$row = $dbr->fetchObject( $res );
 	$admins = $row->total;
Index: trunk/phase3/includes/DefaultSettings.php
===================================================================
--- trunk/phase3/includes/DefaultSettings.php	(revision 9366)
+++ trunk/phase3/includes/DefaultSettings.php	(revision 9367)
@@ -671,13 +671,26 @@
 $wgAutoblockExpiry		= 86400; # Number of seconds before autoblock entries expire
 
 /**
- * Static user groups serialized record
- * To avoid database access, you can set this to a user groups record as returned 
- * by Special:Groups with the magic parameter showrecord=1. This will however mean 
- * that you won't be able to edit them at runtime.
+ * Permission keys given to users in each group.
+ * All users are implicitly in the '*' group including anonymous visitors;
+ * logged-in users are all implicitly in the 'user' group. These will be
+ * combined with the permissions of all groups that a given user is listed
+ * in in the user_groups table.
  */
-$wgStaticGroups = false;
+$wgGroupPermissions = array(
+	'*'          => array( 'read', 'createaccount' ),
+	'user'       => array( 'read', 'move' ),
+	
+	'bot'        => array( 'bot' ),
+	'sysop'      => array( 'createaccount', 'patrol', 'protect', 'delete',
+	                       'rollback', 'block', 'editinterface' ),
+	'bureaucrat' => array( 'userrights' ),
+	'steward'    => array( 'makesysop' ), # technically this is for an extension...
+	'developer'  => array( 'siteadmin' ),
+);
 
+
+
 # Proxy scanner settings
 #
 
@@ -1319,15 +1332,7 @@
 # $wgLocaltimezone = 'CET';
 $wgLocaltimezone = null;
 
-/**
- * User level management
- * The number is the database id of a group you want users to be attached by
- * default. A better interface should be coded [av]
- */
-$wgAnonGroupId = 1;
-$wgLoggedInGroupId = 2;
 
-
 /**
  * When translating messages with wfMsg(), it is not always clear what should be
  * considered UI messages and what shoud be content messages.
Index: trunk/phase3/includes/SpecialPage.php
===================================================================
--- trunk/phase3/includes/SpecialPage.php	(revision 9366)
+++ trunk/phase3/includes/SpecialPage.php	(revision 9367)
@@ -72,7 +72,7 @@
 	'Lockdb'		=> new SpecialPage( 'Lockdb', 'siteadmin' ),
 	'Unlockdb'		=> new SpecialPage( 'Unlockdb', 'siteadmin' ),
 	'Userrights'	=> new SpecialPage( 'Userrights', 'userrights' ),
-	'Groups'		=> new SpecialPage( 'Groups' ),
+	// 'Groups'		=> new SpecialPage( 'Groups' ), # currently borken
 );
 
 global $wgUseValidation ;
Index: trunk/phase3/includes/SpecialListusers.php
===================================================================
--- trunk/phase3/includes/SpecialListusers.php	(revision 9366)
+++ trunk/phase3/includes/SpecialListusers.php	(revision 9367)
@@ -64,18 +64,22 @@
 		// form header
 		$out = '<form method="get" action="'.$action.'">' .
 				'<input type="hidden" name="title" value="'.$special.'" />' .
-				wfMsg( 'grouplevels-editgroup-name' ) . '<select name="group">';
+				wfMsg( 'groups-editgroup-name' ) . '<select name="group">';
 
 		// get all group names and IDs
-		$groups =& Group::getAllGroups();
+		$groups = User::getAllGroups();
 		
 		// we want a default empty group
 		$out.= '<option value=""></option>';
 		
 		// build the dropdown list menu using datas from the database
 		foreach ( $groups as $group ) {
-			$selected = ($group->getId() == $this->requestedGroup) ? ' selected ' : '' ;
-			$out.= '<option value="'.$group->getId().'" '.$selected.'>'.$group->getExpandedName().'</option>';
+			$selected = ($group == $this->requestedGroup);
+			$out .= wfElement( 'option',
+				array_merge(
+					array( 'value' => $group ),
+					$selected ? array( 'selected' => 'selected' ) : array() ),
+				User::getGroupName( $group ) );
 		}
 		$out .= '</select> ';
 
@@ -89,24 +93,16 @@
 	
 	function getSQL() {
 		$dbr =& wfGetDB( DB_SLAVE );
-	/* system showing possible actions for users
 		$user = $dbr->tableName( 'user' );
-		$user_rights = $dbr->tableName( 'user_rights' );
-		$userspace = Namespace::getUser();
-		return "SELECT ur_rights as type, $userspace as namespace, user_name as title, " .
-			"user_name as value FROM $user LEFT JOIN $user_rights ON user_id = ur_user";
-	*/
-	/** Show groups instead */
-		$user = $dbr->tableName( 'user' );
 		$user_groups = $dbr->tableName( 'user_groups' );
 		
 		$userspace = NS_USER;
-		$sql = "SELECT CONCAT('Listusers ', ug_group) as type, $userspace AS namespace, user_name AS title, user_name as value " .
+		$sql = "SELECT 'Listusers' as type, $userspace AS namespace, user_name AS title, ug_group as value " .
 			"FROM $user ".
 			"LEFT JOIN $user_groups ON user_id =ug_user ";
 
 		if($this->requestedGroup != '') {
-			$sql .=  "WHERE ug_group = '" . IntVal( $this->requestedGroup ) . "' ";
+			$sql .=  'WHERE ug_group = ' . $dbr->addQuotes( $this->requestedGroup ) . ' ';
 			if($this->requestedUser != '') {
 				$sql .= "AND user_name = " . $dbr->addQuotes( $this->requestedUser ) . ' ';
 			}
@@ -138,10 +134,7 @@
 	function clearGroups() {
 		$this->concatGroups = '';	
 	}
-/*
-	var $previousResult = false;
-	var $concatGroups = '';
-*/
+	
 	function formatResult( $skin, $result ) {
 		global $wgContLang;
 		$name = false;
@@ -155,9 +148,9 @@
 		}
 
 		if( is_object( $result ) && $result->type != '') {
-			$group = Group::newFromId( intval( strstr( $result->type, ' ' ) ) );
+			$group = $result->value;
 			if ( $group ) {
-				$groupName = $group->getExpandedName();
+				$groupName = User::getGroupName( $group );
 				$this->appendGroups( $skin->makeLink( wfMsgForContent( 'administrators' ), $groupName ) );
 			}
 		}
Index: trunk/phase3/RELEASE-NOTES
===================================================================
--- trunk/phase3/RELEASE-NOTES	(revision 9366)
+++ trunk/phase3/RELEASE-NOTES	(revision 9367)
@@ -272,6 +272,7 @@
 * (bug 2309) Allow templates and template parameters in HTML attribute zone,
   with proper validation checks. (regression from fix for 2304)
 * Disallow close tags and enforce empty tags for <hr> and <br>
+* Changed user_groups format quite a bit.
 
 
 === Caveats ===

Status & tagging log

  • 15:03, 12 September 2011 Meno25 (Talk | contribs) changed the status of r9367 [removed: ok added: old]
  • 14:05, 18 June 2009 ^demon (Talk | contribs) changed the status of r9367 [removed: new added: ok]
Personal tools
Namespaces
Variants
Views
Actions
Site
Support
Download
Development
Communication
Toolbox