MediaWiki  master
Autopromote.php
Go to the documentation of this file.
1 <?php
25 
30 class Autopromote {
37  public static function getAutopromoteGroups( User $user ) {
38  global $wgAutopromote;
39 
40  $promote = [];
41 
42  foreach ( $wgAutopromote as $group => $cond ) {
43  if ( self::recCheckCondition( $cond, $user ) ) {
44  $promote[] = $group;
45  }
46  }
47 
48  Hooks::run( 'GetAutoPromoteGroups', [ $user, &$promote ] );
49 
50  return $promote;
51  }
52 
65  public static function getAutopromoteOnceGroups( User $user, $event ) {
66  global $wgAutopromoteOnce;
67 
68  $promote = [];
69 
70  if ( isset( $wgAutopromoteOnce[$event] ) && count( $wgAutopromoteOnce[$event] ) ) {
71  $currentGroups = $user->getGroups();
72  $formerGroups = $user->getFormerGroups();
73  foreach ( $wgAutopromoteOnce[$event] as $group => $cond ) {
74  // Do not check if the user's already a member
75  if ( in_array( $group, $currentGroups ) ) {
76  continue;
77  }
78  // Do not autopromote if the user has belonged to the group
79  if ( in_array( $group, $formerGroups ) ) {
80  continue;
81  }
82  // Finally - check the conditions
83  if ( self::recCheckCondition( $cond, $user ) ) {
84  $promote[] = $group;
85  }
86  }
87  }
88 
89  return $promote;
90  }
91 
108  private static function recCheckCondition( $cond, User $user ) {
109  $validOps = [ '&', '|', '^', '!' ];
110 
111  if ( is_array( $cond ) && count( $cond ) >= 2 && in_array( $cond[0], $validOps ) ) {
112  # Recursive condition
113  if ( $cond[0] == '&' ) { // AND (all conds pass)
114  foreach ( array_slice( $cond, 1 ) as $subcond ) {
115  if ( !self::recCheckCondition( $subcond, $user ) ) {
116  return false;
117  }
118  }
119 
120  return true;
121  } elseif ( $cond[0] == '|' ) { // OR (at least one cond passes)
122  foreach ( array_slice( $cond, 1 ) as $subcond ) {
123  if ( self::recCheckCondition( $subcond, $user ) ) {
124  return true;
125  }
126  }
127 
128  return false;
129  } elseif ( $cond[0] == '^' ) { // XOR (exactly one cond passes)
130  if ( count( $cond ) > 3 ) {
131  wfWarn( 'recCheckCondition() given XOR ("^") condition on three or more conditions.' .
132  ' Check your $wgAutopromote and $wgAutopromoteOnce settings.' );
133  }
134  return self::recCheckCondition( $cond[1], $user )
135  xor self::recCheckCondition( $cond[2], $user );
136  } elseif ( $cond[0] == '!' ) { // NOT (no conds pass)
137  foreach ( array_slice( $cond, 1 ) as $subcond ) {
138  if ( self::recCheckCondition( $subcond, $user ) ) {
139  return false;
140  }
141  }
142 
143  return true;
144  }
145  }
146  // If we got here, the array presumably does not contain other conditions;
147  // it's not recursive. Pass it off to self::checkCondition.
148  if ( !is_array( $cond ) ) {
149  $cond = [ $cond ];
150  }
151 
152  return self::checkCondition( $cond, $user );
153  }
154 
165  private static function checkCondition( $cond, User $user ) {
166  global $wgEmailAuthentication;
167  if ( count( $cond ) < 1 ) {
168  return false;
169  }
170 
171  switch ( $cond[0] ) {
173  if ( Sanitizer::validateEmail( $user->getEmail() ) ) {
174  if ( $wgEmailAuthentication ) {
175  return (bool)$user->getEmailAuthenticationTimestamp();
176  } else {
177  return true;
178  }
179  }
180  return false;
181  case APCOND_EDITCOUNT:
182  $reqEditCount = $cond[1];
183 
184  // T157718: Avoid edit count lookup if specified edit count is 0 or invalid
185  if ( $reqEditCount <= 0 ) {
186  return true;
187  }
188  return $user->getEditCount() >= $reqEditCount;
189  case APCOND_AGE:
190  $age = time() - (int)wfTimestampOrNull( TS_UNIX, $user->getRegistration() );
191  return $age >= $cond[1];
193  $age = time() - (int)wfTimestampOrNull( TS_UNIX, $user->getFirstEditTimestamp() );
194  return $age >= $cond[1];
195  case APCOND_INGROUPS:
196  $groups = array_slice( $cond, 1 );
197  return count( array_intersect( $groups, $user->getGroups() ) ) == count( $groups );
198  case APCOND_ISIP:
199  return $cond[1] == $user->getRequest()->getIP();
200  case APCOND_IPINRANGE:
201  return IP::isInRange( $user->getRequest()->getIP(), $cond[1] );
202  case APCOND_BLOCKED:
203  return $user->getBlock() && $user->getBlock()->isSitewide();
204  case APCOND_ISBOT:
205  return in_array( 'bot', MediaWikiServices::getInstance()
207  ->getGroupPermissions( $user->getGroups() ) );
208  default:
209  $result = null;
210  Hooks::run( 'AutopromoteCondition', [ $cond[0],
211  array_slice( $cond, 1 ), $user, &$result ] );
212  if ( $result === null ) {
213  throw new MWException( "Unrecognized condition {$cond[0]} for autopromotion!" );
214  }
215 
216  return (bool)$result;
217  }
218  }
219 }
getEmail()
Get the user&#39;s e-mail address.
Definition: User.php:2852
wfWarn( $msg, $callerOffset=1, $level=E_USER_NOTICE)
Send a warning either to the debug log or in a PHP error depending on $wgDevelopmentWarnings.
const APCOND_AGE
Definition: Defines.php:186
getFirstEditTimestamp()
Get the timestamp of the first edit.
Definition: User.php:4760
const APCOND_ISBOT
Definition: Defines.php:193
getBlock( $fromReplica=true)
Get the block affecting the user, or null if the user is not blocked.
Definition: User.php:2117
wfTimestampOrNull( $outputtype=TS_UNIX, $ts=null)
Return a formatted timestamp, or null if input is null.
const APCOND_BLOCKED
Definition: Defines.php:192
const APCOND_ISIP
Definition: Defines.php:189
static validateEmail( $addr)
Does a string look like an e-mail address?
Definition: Sanitizer.php:2127
The User object encapsulates all of the user-specific settings (user_id, name, rights, email address, options, last login time).
Definition: User.php:51
getPermissionManager()
getRegistration()
Get the timestamp of account creation.
Definition: User.php:4746
static checkCondition( $cond, User $user)
As recCheckCondition, but not recursive.
This class checks if user can get extra rights because of conditions specified in $wgAutopromote...
Definition: Autopromote.php:30
static getAutopromoteGroups(User $user)
Get the groups for the given user based on $wgAutopromote.
Definition: Autopromote.php:37
const APCOND_AGE_FROM_EDIT
Definition: Defines.php:191
static isInRange( $addr, $range)
Determine if a given IPv4/IPv6 address is in a given CIDR network.
Definition: IP.php:637
$wgAutopromote
Array containing the conditions of automatic promotion of a user to specific groups.
static recCheckCondition( $cond, User $user)
Recursively check a condition.
$wgEmailAuthentication
Require email authentication before sending mail to an email address.
getRequest()
Get the WebRequest object to use with this object.
Definition: User.php:3702
getGroups()
Get the list of explicit group memberships this user has.
Definition: User.php:3362
getEmailAuthenticationTimestamp()
Get the timestamp of the user&#39;s e-mail authentication.
Definition: User.php:2862
const APCOND_EMAILCONFIRMED
Definition: Defines.php:187
const APCOND_INGROUPS
Definition: Defines.php:188
getEditCount()
Get the user&#39;s edit count.
Definition: User.php:3464
const APCOND_IPINRANGE
Definition: Defines.php:190
const APCOND_EDITCOUNT
Definition: Defines.php:185
static getAutopromoteOnceGroups(User $user, $event)
Get the groups for the given user based on the given criteria.
Definition: Autopromote.php:65
$wgAutopromoteOnce
Automatically add a usergroup to any user who matches certain conditions.
getFormerGroups()
Returns the groups the user has belonged to.
Definition: User.php:3440
static run( $event, array $args=[], $deprecatedVersion=null)
Call hook functions defined in Hooks::register and $wgHooks.
Definition: Hooks.php:200