2007-12-23 11:38:24 +00:00
|
|
|
<?php
|
2012-05-22 18:06:30 +00:00
|
|
|
/**
|
|
|
|
|
* Automatic user rights promotion based on conditions specified
|
|
|
|
|
* in $wgAutopromote.
|
|
|
|
|
*
|
|
|
|
|
* 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
|
|
|
|
|
*/
|
|
|
|
|
|
2007-12-23 11:38:24 +00:00
|
|
|
/**
|
|
|
|
|
* This class checks if user can get extra rights
|
|
|
|
|
* because of conditions specified in $wgAutopromote
|
|
|
|
|
*/
|
2007-12-23 19:53:49 +00:00
|
|
|
class Autopromote {
|
|
|
|
|
/**
|
|
|
|
|
* Get the groups for the given user based on $wgAutopromote.
|
|
|
|
|
*
|
2011-05-28 17:18:50 +00:00
|
|
|
* @param $user User The user to get the groups for
|
2007-12-23 19:53:49 +00:00
|
|
|
* @return array Array of groups to promote to.
|
|
|
|
|
*/
|
|
|
|
|
public static function getAutopromoteGroups( User $user ) {
|
2007-12-23 11:38:24 +00:00
|
|
|
global $wgAutopromote;
|
2010-05-30 14:48:30 +00:00
|
|
|
|
2007-12-23 11:38:24 +00:00
|
|
|
$promote = array();
|
2010-05-30 14:48:30 +00:00
|
|
|
|
|
|
|
|
foreach ( $wgAutopromote as $group => $cond ) {
|
2010-10-21 18:26:17 +00:00
|
|
|
if ( self::recCheckCondition( $cond, $user ) ) {
|
2007-12-23 11:38:24 +00:00
|
|
|
$promote[] = $group;
|
2010-10-21 18:26:17 +00:00
|
|
|
}
|
2007-12-23 11:38:24 +00:00
|
|
|
}
|
2009-06-18 02:50:16 +00:00
|
|
|
|
2008-08-18 18:03:49 +00:00
|
|
|
wfRunHooks( 'GetAutoPromoteGroups', array( $user, &$promote ) );
|
2009-06-18 02:50:16 +00:00
|
|
|
|
2008-01-14 18:52:55 +00:00
|
|
|
return $promote;
|
2007-12-23 11:38:24 +00:00
|
|
|
}
|
2011-06-25 05:21:53 +00:00
|
|
|
|
2011-06-25 02:52:30 +00:00
|
|
|
/**
|
|
|
|
|
* Get the groups for the given user based on the given criteria.
|
2011-06-26 19:16:04 +00:00
|
|
|
*
|
2011-06-25 02:52:30 +00:00
|
|
|
* Does not return groups the user already belongs to or has once belonged.
|
2011-06-26 19:16:04 +00:00
|
|
|
*
|
2012-02-09 18:01:54 +00:00
|
|
|
* @param $user User The user to get the groups for
|
2011-06-25 17:59:42 +00:00
|
|
|
* @param $event String key in $wgAutopromoteOnce (each one has groups/criteria)
|
|
|
|
|
*
|
2011-06-25 02:52:30 +00:00
|
|
|
* @return array Groups the user should be promoted to.
|
2011-06-25 17:59:42 +00:00
|
|
|
*
|
|
|
|
|
* @see $wgAutopromoteOnce
|
2011-06-25 02:52:30 +00:00
|
|
|
*/
|
2011-06-25 05:21:53 +00:00
|
|
|
public static function getAutopromoteOnceGroups( User $user, $event ) {
|
|
|
|
|
global $wgAutopromoteOnce;
|
2011-06-25 04:58:48 +00:00
|
|
|
|
2011-06-25 05:21:53 +00:00
|
|
|
$promote = array();
|
2011-06-25 04:58:48 +00:00
|
|
|
|
2011-06-25 05:21:53 +00:00
|
|
|
if ( isset( $wgAutopromoteOnce[$event] ) && count( $wgAutopromoteOnce[$event] ) ) {
|
|
|
|
|
$currentGroups = $user->getGroups();
|
2011-06-26 21:44:55 +00:00
|
|
|
$formerGroups = $user->getFormerGroups();
|
2011-06-25 05:21:53 +00:00
|
|
|
foreach ( $wgAutopromoteOnce[$event] as $group => $cond ) {
|
|
|
|
|
// Do not check if the user's already a member
|
|
|
|
|
if ( in_array( $group, $currentGroups ) ) {
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
// Do not autopromote if the user has belonged to the group
|
|
|
|
|
if ( in_array( $group, $formerGroups ) ) {
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
// Finally - check the conditions
|
|
|
|
|
if ( self::recCheckCondition( $cond, $user ) ) {
|
|
|
|
|
$promote[] = $group;
|
|
|
|
|
}
|
2011-06-25 04:58:48 +00:00
|
|
|
}
|
2011-06-25 02:52:30 +00:00
|
|
|
}
|
2011-06-25 04:58:48 +00:00
|
|
|
|
2011-06-25 02:52:30 +00:00
|
|
|
return $promote;
|
|
|
|
|
}
|
2007-12-23 11:38:24 +00:00
|
|
|
|
2007-12-23 19:53:49 +00:00
|
|
|
/**
|
|
|
|
|
* Recursively check a condition. Conditions are in the form
|
2011-06-26 04:12:05 +00:00
|
|
|
* array( '&' or '|' or '^' or '!', cond1, cond2, ... )
|
2007-12-23 19:53:49 +00:00
|
|
|
* where cond1, cond2, ... are themselves conditions; *OR*
|
|
|
|
|
* APCOND_EMAILCONFIRMED, *OR*
|
|
|
|
|
* array( APCOND_EMAILCONFIRMED ), *OR*
|
|
|
|
|
* array( APCOND_EDITCOUNT, number of edits ), *OR*
|
|
|
|
|
* array( APCOND_AGE, seconds since registration ), *OR*
|
|
|
|
|
* similar constructs defined by extensions.
|
|
|
|
|
* This function evaluates the former type recursively, and passes off to
|
|
|
|
|
* self::checkCondition for evaluation of the latter type.
|
|
|
|
|
*
|
WARNING: HUGE COMMIT
Doxygen documentation update:
* Changed alls @addtogroup to @ingroup. @addtogroup adds the comment to the group description, but doesn't add the file, class, function, ... to the group like @ingroup does. See for example http://svn.wikimedia.org/doc/group__SpecialPage.html where it's impossible to see related files, classes, ... that should belong to that group.
* Added @file to file description, it seems that it should be explicitely decalred for file descriptions, otherwise doxygen will think that the comment document the first class, variabled, function, ... that is in that file.
* Removed some empty comments
* Removed some ?>
Added following groups:
* ExternalStorage
* JobQueue
* MaintenanceLanguage
One more thing: there are still a lot of warnings when generating the doc.
2008-05-20 17:13:28 +00:00
|
|
|
* @param $cond Mixed: a condition, possibly containing other conditions
|
2011-05-28 18:58:51 +00:00
|
|
|
* @param $user User The user to check the conditions against
|
2007-12-23 19:53:49 +00:00
|
|
|
* @return bool Whether the condition is true
|
|
|
|
|
*/
|
|
|
|
|
private static function recCheckCondition( $cond, User $user ) {
|
2008-06-07 05:13:25 +00:00
|
|
|
$validOps = array( '&', '|', '^', '!' );
|
2010-05-30 14:48:30 +00:00
|
|
|
|
|
|
|
|
if ( is_array( $cond ) && count( $cond ) >= 2 && in_array( $cond[0], $validOps ) ) {
|
2007-12-23 19:53:49 +00:00
|
|
|
# Recursive condition
|
2011-06-26 04:50:24 +00:00
|
|
|
if ( $cond[0] == '&' ) { // AND (all conds pass)
|
2010-05-30 14:48:30 +00:00
|
|
|
foreach ( array_slice( $cond, 1 ) as $subcond ) {
|
|
|
|
|
if ( !self::recCheckCondition( $subcond, $user ) ) {
|
2007-12-23 11:38:24 +00:00
|
|
|
return false;
|
2010-05-30 14:48:30 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2007-12-23 11:38:24 +00:00
|
|
|
return true;
|
2011-06-26 04:50:24 +00:00
|
|
|
} elseif ( $cond[0] == '|' ) { // OR (at least one cond passes)
|
2010-05-30 14:48:30 +00:00
|
|
|
foreach ( array_slice( $cond, 1 ) as $subcond ) {
|
|
|
|
|
if ( self::recCheckCondition( $subcond, $user ) ) {
|
2007-12-23 11:38:24 +00:00
|
|
|
return true;
|
2010-05-30 14:48:30 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2007-12-23 11:38:24 +00:00
|
|
|
return false;
|
2011-06-26 04:50:24 +00:00
|
|
|
} elseif ( $cond[0] == '^' ) { // XOR (exactly one cond passes)
|
2011-06-28 02:56:45 +00:00
|
|
|
if ( count( $cond ) > 3 ) {
|
|
|
|
|
wfWarn( 'recCheckCondition() given XOR ("^") condition on three or more conditions. Check your $wgAutopromote and $wgAutopromoteOnce settings.' );
|
2007-12-23 19:53:49 +00:00
|
|
|
}
|
2011-06-28 02:56:45 +00:00
|
|
|
return self::recCheckCondition( $cond[1], $user )
|
|
|
|
|
xor self::recCheckCondition( $cond[2], $user );
|
2011-06-26 04:50:24 +00:00
|
|
|
} elseif ( $cond[0] == '!' ) { // NOT (no conds pass)
|
2010-05-30 14:48:30 +00:00
|
|
|
foreach ( array_slice( $cond, 1 ) as $subcond ) {
|
|
|
|
|
if ( self::recCheckCondition( $subcond, $user ) ) {
|
2008-06-07 05:13:25 +00:00
|
|
|
return false;
|
2010-05-30 14:48:30 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2008-06-07 05:13:25 +00:00
|
|
|
return true;
|
2007-12-23 11:38:24 +00:00
|
|
|
}
|
|
|
|
|
}
|
2007-12-23 19:53:49 +00:00
|
|
|
# If we got here, the array presumably does not contain other condi-
|
|
|
|
|
# tions; it's not recursive. Pass it off to self::checkCondition.
|
2010-05-30 14:48:30 +00:00
|
|
|
if ( !is_array( $cond ) ) {
|
2007-12-23 11:38:24 +00:00
|
|
|
$cond = array( $cond );
|
2010-05-30 14:48:30 +00:00
|
|
|
}
|
|
|
|
|
|
2007-12-23 11:38:24 +00:00
|
|
|
return self::checkCondition( $cond, $user );
|
|
|
|
|
}
|
|
|
|
|
|
2007-12-23 19:53:49 +00:00
|
|
|
/**
|
|
|
|
|
* As recCheckCondition, but *not* recursive. The only valid conditions
|
|
|
|
|
* are those whose first element is APCOND_EMAILCONFIRMED/APCOND_EDITCOUNT/
|
|
|
|
|
* APCOND_AGE. Other types will throw an exception if no extension evalu-
|
|
|
|
|
* ates them.
|
|
|
|
|
*
|
WARNING: HUGE COMMIT
Doxygen documentation update:
* Changed alls @addtogroup to @ingroup. @addtogroup adds the comment to the group description, but doesn't add the file, class, function, ... to the group like @ingroup does. See for example http://svn.wikimedia.org/doc/group__SpecialPage.html where it's impossible to see related files, classes, ... that should belong to that group.
* Added @file to file description, it seems that it should be explicitely decalred for file descriptions, otherwise doxygen will think that the comment document the first class, variabled, function, ... that is in that file.
* Removed some empty comments
* Removed some ?>
Added following groups:
* ExternalStorage
* JobQueue
* MaintenanceLanguage
One more thing: there are still a lot of warnings when generating the doc.
2008-05-20 17:13:28 +00:00
|
|
|
* @param $cond Array: A condition, which must not contain other conditions
|
2011-05-28 18:58:51 +00:00
|
|
|
* @param $user User The user to check the condition against
|
2007-12-23 19:53:49 +00:00
|
|
|
* @return bool Whether the condition is true for the user
|
|
|
|
|
*/
|
|
|
|
|
private static function checkCondition( $cond, User $user ) {
|
2010-08-12 14:25:07 +00:00
|
|
|
global $wgEmailAuthentication;
|
2010-05-30 14:48:30 +00:00
|
|
|
if ( count( $cond ) < 1 ) {
|
2007-12-23 11:38:24 +00:00
|
|
|
return false;
|
2010-05-30 14:48:30 +00:00
|
|
|
}
|
|
|
|
|
|
2007-12-23 11:38:24 +00:00
|
|
|
switch( $cond[0] ) {
|
|
|
|
|
case APCOND_EMAILCONFIRMED:
|
2011-06-26 19:16:04 +00:00
|
|
|
if ( Sanitizer::validateEmail( $user->getEmail() ) ) {
|
2010-05-30 14:48:30 +00:00
|
|
|
if ( $wgEmailAuthentication ) {
|
2008-05-15 15:38:51 +00:00
|
|
|
return (bool)$user->getEmailAuthenticationTimestamp();
|
2007-12-23 11:38:24 +00:00
|
|
|
} else {
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return false;
|
|
|
|
|
case APCOND_EDITCOUNT:
|
2007-12-23 19:53:49 +00:00
|
|
|
return $user->getEditCount() >= $cond[1];
|
2007-12-23 11:38:24 +00:00
|
|
|
case APCOND_AGE:
|
|
|
|
|
$age = time() - wfTimestampOrNull( TS_UNIX, $user->getRegistration() );
|
|
|
|
|
return $age >= $cond[1];
|
2009-01-03 12:53:08 +00:00
|
|
|
case APCOND_AGE_FROM_EDIT:
|
|
|
|
|
$age = time() - wfTimestampOrNull( TS_UNIX, $user->getFirstEditTimestamp() );
|
|
|
|
|
return $age >= $cond[1];
|
2008-01-14 18:52:55 +00:00
|
|
|
case APCOND_INGROUPS:
|
|
|
|
|
$groups = array_slice( $cond, 1 );
|
|
|
|
|
return count( array_intersect( $groups, $user->getGroups() ) ) == count( $groups );
|
2008-12-14 20:49:19 +00:00
|
|
|
case APCOND_ISIP:
|
2011-08-18 20:03:30 +00:00
|
|
|
return $cond[1] == $user->getRequest()->getIP();
|
2008-12-14 20:49:19 +00:00
|
|
|
case APCOND_IPINRANGE:
|
2011-08-18 20:03:30 +00:00
|
|
|
return IP::isInRange( $user->getRequest()->getIP(), $cond[1] );
|
2009-06-18 02:50:16 +00:00
|
|
|
case APCOND_BLOCKED:
|
|
|
|
|
return $user->isBlocked();
|
2011-06-26 04:12:05 +00:00
|
|
|
case APCOND_ISBOT:
|
|
|
|
|
return in_array( 'bot', User::getGroupPermissions( $user->getGroups() ) );
|
2007-12-23 11:38:24 +00:00
|
|
|
default:
|
2007-12-23 19:53:49 +00:00
|
|
|
$result = null;
|
2007-12-23 18:33:46 +00:00
|
|
|
wfRunHooks( 'AutopromoteCondition', array( $cond[0], array_slice( $cond, 1 ), $user, &$result ) );
|
2010-05-30 14:48:30 +00:00
|
|
|
if ( $result === null ) {
|
2007-12-23 19:53:49 +00:00
|
|
|
throw new MWException( "Unrecognized condition {$cond[0]} for autopromotion!" );
|
|
|
|
|
}
|
2010-05-30 14:48:30 +00:00
|
|
|
|
2010-09-27 14:24:13 +00:00
|
|
|
return (bool)$result;
|
2007-12-23 11:38:24 +00:00
|
|
|
}
|
|
|
|
|
}
|
2007-12-23 19:53:49 +00:00
|
|
|
}
|