more wikis
 
[Dantman]

Dantman 2,347 edits since August 19, 2006

2,347

User:Dantman/GE Extended/Custom Extensions/RightsControl/SpecialRightsControl.php

Wikia - creating communities

<?php

/**
 * The RightsControl Extension's task's are:
 * - Managements of UserRights in a manor similar to Special:Userrights but safe like
 *   	Special:Makesysop, Special:Makebot, and Special:Desysop. 
 *
 * @package GENetwork Extensions
 * @subpackage RightsControl 
 * @author Daniel Friesen (http://www.wikia.com/wiki/User:Dantman) (dan_the_man@telus.net)
 * @license http://www.gnu.org/copyleft/gpl.html GNU General Public Licence 2.0 or later
 */

if( !defined( 'MEDIAWIKI' ) ) die( "This is an extension to the MediaWiki package and cannot be run standalone." );

require_once( "$IP/includes/SpecialPage.php" );

/**
 * Constructor
 */
class SpecialRightsControl extends SpecialPage {
	function SpecialRightsControl() {
		global $wgRequest;
		SpecialPage::SpecialPage( 'RightsControl', 'rc-use', true, false, 'default', false );
	}
	
	/**
	 * Execute
	 */
	function execute( $par = null ) {
		global $wgUser, $wgOut, $wgRequest;
	
		# Check rights
		if ( $wgUser->isAllowed( 'userrights' ) ) {
			$wgOut->redirect( SpecialPage::getTitleFor( 'Userrights' )->getFullURL() );
			return false;
		}
		wfDebug( $wgRequest->getBool( 'pass-error', false ) . "\n" . $wgRequest->getText( 'pass-error', '' ) );
		if ( !$wgUser->isAllowed( 'rc-use' ) ) {
			$wgOut->permissionRequired( "re-use" );
			return false;
		}
	
		# Don't allow blocked users to move pages
		if ( $wgUser->isBlocked() ) {
			$wgOut->blockedPage();
			return false;
		}
	
		# Check for database lock
		if ( wfReadOnly() ) {
			$wgOut->readOnlyPage();
			return false;
		}
		
		$this->setHeaders();
		
		$f = new SpecialRightsControlForm( $par );
		//Show Error form if we have errors
		if( count( $f->errors ) > 0 ) $f->showErrorForm();
		//Always show the user form
		$f->showUserForm();
		if( !is_null( $f->userObject ) && $f->userObject->getID() != 0 ) {
			//Continue with this if we have a user
			if( $wgRequest->wasPosted() && $wgRequest->getCheck( 'yes-dogroups' ) && count( $f->errors ) <= 0 ) {
				//If there was a yes from the confirmation form
				//	and we have no errors then run the rights changer
				//	and redirect us back after finished to refresh the info
				$f->doGroups();
				$wgOut->redirect( SpecialPage::getTitleFor( 'RightsControl' )->getFullURL(
					'username='.wfUrlencode($f->userName).'&rightsControlMainpageFallback=true' ) );
			} elseif( $wgRequest->wasPosted() && $wgRequest->getCheck( 'savegroups' ) && count( $f->errors ) <= 0 ) {
				//If we requested an action display the confirmation form
				$f->showConfirmForm();
			} else {
				//If nothing else, show the rights form if we have a user chosen
				$f->showRightsForm();
			}
		}
	}
}

class SpecialRightsControlForm {
	var $allGroups, $selfAction, $errors;
	var $userName, $userObject, $userGroups;
	var $addGroups, $removeGroups;
	
	/**
	 * Setup
	 */
	function SpecialRightsControlForm( $par = NULL ) {
		global $wgOut, $wgUser, $wgRequest;
		
		$titleObj = SpecialPage::getTitleFor( 'RightsControl' );
		$this->selfAction   = $titleObj->escapeLocalURL();
		$this->allGroups    = User::getAllGroups();
		
		$this->userName     = $wgRequest->getVal( 'username', NULL );
		$this->userObject   = User::newFromName( $this->userName );
		$this->userGroups   = !is_null( $this->userObject ) ? $this->userObject->getGroups() : array();
		$this->addGroups    = $wgRequest->getArray( 'add', array() );
		$this->removeGroups = $wgRequest->getArray( 'remove', array() );
		
		$this->errors = array();
		
		if( ( is_null( $this->userObject ) && $wgRequest->wasPosted() ) || $this->userName === '' ) {
			$this->errors[] = $wgOut->parse( wfMsg( 'nouserspecified' ) );
		} elseif( !is_null( $this->userObject ) && $this->userObject->getID() == 0 ) {
			$this->errors[] = $wgOut->parse( wfMsg( 'nosuchusershort', wfEscapeWikiText( $this->userName ) ) );
		} else {
			if( $wgRequest->wasPosted() && $wgRequest->getCheck( 'savegroups' ) ) {
				//We requested action, validate it
				if( count( $this->addGroups + $this->removeGroups ) > 0 ) {
					//If we selected groups to change
					foreach( $this->addGroups as $group ) {
						if( in_array( $group, $this->userObject->getGroups() ) ) {
							//User already has this group to be added
							$this->errors[] = $wgOut->parse( wfMsg( 'userrights-alreadyhas', $group ) );
						}
						if( !$wgUser->isAllowed( "rc-mk-$group" ) ) {
							//You can't add this group
							$this->errors[] = $wgOut->parse( wfMsg( 'badaccess-addgroup', $group ) );
						}
					}
					foreach( $this->removeGroups as $group ) {
						//User dosen't have this group to be removed
						if( !in_array( $group, $this->userObject->getGroups() ) ) {
							$this->errors[] = $wgOut->parse( wfMsg( 'userrights-isnotgroup', $group ) );
						}
						if( !$wgUser->isAllowed( "rc-de-$group" ) &&
							( !$wgUser->isAllowed( "rc-sr-$group" ) &&
								$wgUser->getName() == $this->userObject->getName() ) ) {
							//You can't remove this group
							$this->errors[] = $wgOut->parse( wfMsg( 'badaccess-removegroup', $group ) );
						}
					}
				} else {
					//You didn't select anything
					$this->errors[] = $wgOut->parse( wfMsg( 'userrights-noneselected' ) );
				}
			}
		}
	}
	
	/**
	 * Error Box
	 */
	function showErrorForm() {
		global $wgOut;
		$wgOut->addHTML(
			Xml::openElement( 'fieldset' ).
			Xml::element( 'legend', NULL, wfMsg( 'userrights-error' ) ).
			Xml::openElement( 'div', array( 'class' => 'error' ) )
		);
		foreach( $this->errors as $error )
			$wgOut->addHTML( $error );
		$wgOut->addHTML(
			Xml::closeElement( 'div' ).
			Xml::closeElement( 'fieldset' )
		);
	}
	
	/**
	 * User Search Form
	 */
	function showUserForm() {
		global $wgOut;
		$wgOut->addHTML(
			Xml::openElement( 'fieldset' ).
			Xml::element( 'legend', NULL, wfMsg( 'userrights-lookup-user' ) ).
			Xml::openElement( 'form', array( 'method' => 'post', 'action' => $this->selfAction, 'name' => 'userform' ) ).
			//Username
			Xml::openElement( 'p' ).
			Xml::inputLabel( wfMsg( 'userrights-user-editname' ),
				'username', 'username', 30,
				$this->userName ).
			Xml::closeElement( 'p' ).
			//Submit
			Xml::openElement( 'p' ).
			Xml::submitButton( wfMsg( 'editusergroup' ) ).
			Xml::closeElement( 'p' ).
			Xml::closeElement( 'form' ).
			Xml::closeElement( 'fieldset' )
		);
	}
	
	/**
	 * User Rights Control Form
	 */
	function showRightsForm() {
		global $wgOut, $wgUser;
		$wgOut->addHTML(
			Xml::openElement( 'fieldset' ).
			Xml::element( 'legend', NULL, wfMsg( 'editusergroup' ) ).
			Xml::openElement( 'form', array( 'method' => 'post', 'action' => $this->selfAction, 'name' => 'userrights' ) ).
			Xml::hidden( 'username', $this->userName ).
			$wgOut->parse( wfMsg( 'editinguser', $this->userObject->getName() ) ).
			Xml::openElement( 'table', array(
				'style' => 'width: 100%;'
			) ).
			Xml::openElement( 'tr' ).
			//Headers
			Xml::element( 'th' ).
			Xml::openElement( 'th' ).
			$wgOut->parse( wfMsg( 'userremovefrom' ) ).
			Xml::closeElement( 'th' ).
			Xml::openElement( 'th' ).
			$wgOut->parse( wfMsg( 'useraddto' ) ).
			Xml::closeElement( 'th' ).
			Xml::closeElement( 'tr' ).
			Xml::openElement( 'tr' ).
			Xml::openElement( 'td', array( 'style' => 'vertical-align: top;' ) ).
			Xml::openElement( 'ul' ).
			$wgOut->parse( wfMsg( 'useringroups' ) )
		);
		//List groups
		foreach( $this->userGroups as $group )
			$wgOut->addHTML(
				Xml::openElement( 'li' ).
				User::makeGroupLinkHTML( $group, User::getGroupMember( $group ) ).
				Xml::closeElement( 'li' )
			);
		$wgOut->addHTML(
			Xml::closeElement( 'ul' ).
			Xml::closeElement( 'td' ).
			Xml::openElement( 'td', array( 'style' => 'width: 20%; text-align: center;' ) ).
			Xml::openElement( 'select', array( 'name' => 'remove[]', 'multiple'=> 'multiple', 'size' => 6 ) )
		);
		//Remove from
		foreach( $this->userGroups as $group )
			if( $wgUser->isAllowed( "rc-de-$group" ) ||
				( $wgUser->isAllowed( "rc-sr-$group" ) &&
					$wgUser->getName() == $this->userObject->getName() ) )
			$wgOut->addHTML( Xml::option( User::getGroupMember( $group ), $group ) );
		$wgOut->addHTML(
			Xml::closeElement( 'select' ).
			Xml::closeElement( 'td' ).
			Xml::openElement( 'td', array( 'style' => 'width: 20%; text-align: center;' ) ).
			Xml::openElement( 'select', array( 'name' => 'add[]', 'multiple'=> 'multiple', 'size' => 6 ) )
		);
		//Add to
		foreach( $this->allGroups as $group )
			if( !in_array( $group, $this->userGroups ) )
			if( $wgUser->isAllowed( "rc-mk-$group" ) )
			$wgOut->addHTML( Xml::option( User::getGroupMember( $group ), $group ) );
		$wgOut->addHTML(
			Xml::closeElement( 'select' ).
			Xml::closeElement( 'td' ).
			Xml::closeElement( 'tr' ).
			Xml::closeElement( 'table' ).
			$wgOut->parse( wfMsg( 'userrights-limitedhelp' ) ).
			$wgOut->parse( wfMsg( 'userrights-groupshelp' ) ).
			Xml::submitButton( wfMsg( 'saveusergroups' ), array( 'name' => 'savegroups' ) ).
			Xml::closeElement( 'form' ).
			Xml::closeElement( 'fieldset' )
		);
	}
	
	/**
	 * Confirmation Form
	 */
	function showConfirmForm() {
		global $wgOut, $wgUser, $wgRequest;
		$wgOut->addHTML(
			Xml::openElement( 'fieldset' ).
			Xml::element( 'legend', NULL, wfMsg( 'userrights-confirm' ) ).
			Xml::openElement( 'form', array( 'method' => 'post', 'action' => $this->selfAction, 'name' => 'userform' ) ).
			Xml::hidden( 'username', $this->userName )
		);
		//Add the change data into hidden elements
		foreach( $this->removeGroups as $group )
			$wgOut->addHTML( Xml::hidden( 'remove[]', $group ) );
		foreach( $this->addGroups as $group )
			$wgOut->addHTML( Xml::hidden( 'add[]', $group ) );
		//Output the info
		foreach( $this->addGroups as $group ) {
			//Add this group
			$wgOut->addHTML(
				$wgOut->parse( wfMsg( 'userrights-addgroup', User::getGroupMember( $group ), $group ) )
			);
			if( $wgUser->isAllowed( "rc-mk-$group" ) && !$wgUser->isAllowed( "rc-de-$group" ) ) {
				//You can add this, but you won't be able to remove it
				$wgOut->addHTML(
					$wgOut->parse( wfMsg( 'userrights-oneway-noremove', User::getGroupMember( $group ), $group ) )
				);
			}
		}
		foreach( $this->removeGroups as $group ) {
			//Remove this group
			$wgOut->addHTML(
				$wgOut->parse( wfMsg( 'userrights-removegroup', User::getGroupMember( $group ), $group ) )
			);
			if( $wgUser->isAllowed( "rc-de-$group" ) && !$wgUser->isAllowed( "rc-mk-$group" ) ) {
				//You can remove this, but you won't be able to add it
				$wgOut->addHTML(
					$wgOut->parse( wfMsg( 'userrights-oneway-nogrant', User::getGroupMember( $group ), $group ) )
				);
			}
		}
		$wgOut->addHTML(
			$wgOut->parse( wfMsg( 'userrights-sure' ) ).
			Xml::submitButton( wfMsg( 'userrights-yes' ), array( 'name' => 'yes-dogroups' ) ).
			Xml::submitButton( wfMsg( 'userrights-no' ), array( 'name' => 'no-dogroups' ) ).
			Xml::closeElement( 'form' ).
			Xml::closeElement( 'fieldset' )
		);
	}
	
	/**
	 * Actually change the groups.
	 * 
	 * @note This function has no validation, this is all done at setup and this must NOT be
	 *       	executed unless you have already made sure that there are no errors in the
	 *       	$errors array.
	 * @note Most of this is actually directly copied from includes/SpecialUserrights.php
	 *       	but while that page itself is a security issue for permissions, the actual
	 *      	code managing permissions is alright, we already made sure everything was ok.
	 */
	function doGroups() {
		$oldGroups = $this->userGroups;
		$newGroups = $oldGroups;
		// remove then add groups
		$newGroups = array_diff($newGroups, $this->removeGroups);
		foreach( $this->removeGroups as $group ) {
			$this->userObject->removeGroup( $group );
		}
		$newGroups = array_merge($newGroups, $this->addGroups);
		foreach( $this->addGroups as $group ) {
			$this->userObject->addGroup( $group );
		}
		$newGroups = array_unique( $newGroups );

		wfDebug( 'oldGroups: ' . print_r( $oldGroups, true ) );
		wfDebug( 'newGroups: ' . print_r( $newGroups, true ) );

		wfRunHooks( 'UserRights', array( &$u, $this->addGroups, $this->removeGroups ) );	
		$log = new LogPage( 'rights' );
		$log->addEntry( 'rights',
			Title::makeTitle( NS_USER, $this->userObject->getName() ), '',
			array(
				implode( ', ', $oldGroups ),
				implode( ', ', $newGroups )
			) );
	}
}

?>