Index: trunk/phase3/includes/Defines.php |
— | — | @@ -277,7 +277,8 @@ |
278 | 278 | # Flags for Parser::replaceLinkHolders |
279 | 279 | define( 'RLH_FOR_UPDATE', 1 ); |
280 | 280 | |
281 | | -#Autopromote conditions |
| 281 | +# Autopromote conditions (must be here and not in Autopromote.php, so that |
| 282 | +# they're loaded for DefaultSettings.php before AutoLoader.php) |
282 | 283 | define( 'APCOND_EDITCOUNT', 1 ); |
283 | 284 | define( 'APCOND_AGE', 2 ); |
284 | 285 | define( 'APCOND_EMAILCONFIRMED', 3 ); |
Index: trunk/phase3/includes/User.php |
— | — | @@ -1652,10 +1652,10 @@ |
1653 | 1653 | if( $this->mId ) { |
1654 | 1654 | $this->mEffectiveGroups[] = 'user'; |
1655 | 1655 | |
1656 | | - $this->mEffectiveGroups = array_merge( |
| 1656 | + $this->mEffectiveGroups = array_unique( array_merge( |
1657 | 1657 | $this->mEffectiveGroups, |
1658 | | - Autopromote::autopromoteUser( $this ) |
1659 | | - ); |
| 1658 | + Autopromote::getAutopromoteGroups( $this ) |
| 1659 | + ) ); |
1660 | 1660 | |
1661 | 1661 | # Hook for additional groups |
1662 | 1662 | wfRunHooks( 'UserEffectiveGroups', array( &$this, &$this->mEffectiveGroups ) ); |
Index: trunk/phase3/includes/DefaultSettings.php |
— | — | @@ -1189,7 +1189,18 @@ |
1190 | 1190 | //$wgAutoConfirmCount = 50; |
1191 | 1191 | |
1192 | 1192 | /** |
1193 | | - * Automatically promote user flags to users that matchs some conditions |
| 1193 | + * Automatically add a usergroup to any user who matches certain conditions. |
| 1194 | + * The format is |
| 1195 | + * array( '&' or '|' or '^', cond1, cond2, ... ) |
| 1196 | + * where cond1, cond2, ... are themselves conditions; *OR* |
| 1197 | + * APCOND_EMAILCONFIRMED, *OR* |
| 1198 | + * array( APCOND_EMAILCONFIRMED ), *OR* |
| 1199 | + * array( APCOND_EDITCOUNT, number of edits ), *OR* |
| 1200 | + * array( APCOND_AGE, seconds since registration ), *OR* |
| 1201 | + * similar constructs defined by extensions. |
| 1202 | + * |
| 1203 | + * Note that EMAILCONFIRMED will always be true if $wgEmailAuthentication is |
| 1204 | + * off! |
1194 | 1205 | */ |
1195 | 1206 | $wgAutopromote = array( |
1196 | 1207 | 'autoconfirmed' => array( '&', |
Index: trunk/phase3/includes/Autopromote.php |
— | — | @@ -4,21 +4,43 @@ |
5 | 5 | * This class checks if user can get extra rights |
6 | 6 | * because of conditions specified in $wgAutopromote |
7 | 7 | */ |
8 | | -class Autopromote { |
9 | | - public static function autopromoteUser( $user ) { |
| 8 | +class Autopromote { |
| 9 | + /** |
| 10 | + * Get the groups for the given user based on $wgAutopromote. |
| 11 | + * |
| 12 | + * @param User $user The user to get the groups for |
| 13 | + * @return array Array of groups to promote to. |
| 14 | + */ |
| 15 | + public static function getAutopromoteGroups( User $user ) { |
10 | 16 | global $wgAutopromote; |
11 | 17 | $promote = array(); |
12 | 18 | foreach( $wgAutopromote as $group => $cond ) { |
13 | 19 | if( self::recCheckCondition( $cond, $user ) ) |
14 | 20 | $promote[] = $group; |
15 | 21 | } |
16 | | - return $promote; |
| 22 | + return array_unique( $promote ); |
17 | 23 | } |
18 | 24 | |
19 | | - //@private |
20 | | - static function recCheckCondition( $cond, $user ) { |
| 25 | + /** |
| 26 | + * Recursively check a condition. Conditions are in the form |
| 27 | + * array( '&' or '|' or '^', cond1, cond2, ... ) |
| 28 | + * where cond1, cond2, ... are themselves conditions; *OR* |
| 29 | + * APCOND_EMAILCONFIRMED, *OR* |
| 30 | + * array( APCOND_EMAILCONFIRMED ), *OR* |
| 31 | + * array( APCOND_EDITCOUNT, number of edits ), *OR* |
| 32 | + * array( APCOND_AGE, seconds since registration ), *OR* |
| 33 | + * similar constructs defined by extensions. |
| 34 | + * This function evaluates the former type recursively, and passes off to |
| 35 | + * self::checkCondition for evaluation of the latter type. |
| 36 | + * |
| 37 | + * @param mixed $cond A condition, possibly containing other conditions |
| 38 | + * @param User $user The user to check the conditions against |
| 39 | + * @return bool Whether the condition is true |
| 40 | + */ |
| 41 | + private static function recCheckCondition( $cond, User $user ) { |
21 | 42 | $validOps = array( '&', '|', '^' ); |
22 | | - if( is_array( $cond ) && count( $cond ) > 0 && in_array( $cond[0], $validOps ) ) { |
| 43 | + if( is_array( $cond ) && count( $cond ) >= 2 && in_array( $cond[0], $validOps ) ) { |
| 44 | + # Recursive condition |
23 | 45 | if( $cond[0] == '&' ) { |
24 | 46 | foreach( array_slice( $cond, 1 ) as $subcond ) |
25 | 47 | if( !self::recCheckCondition( $subcond, $user ) ) |
— | — | @@ -30,23 +52,41 @@ |
31 | 53 | return true; |
32 | 54 | return false; |
33 | 55 | } elseif( $cond[0] == '^' ) { |
34 | | - if( count( $cond ) < 3 ) |
35 | | - return false; |
36 | | - return self::recCheckCondition( $cond[1], $user ) |
37 | | - xor self::recCheckCondition( $cond[2], $user ); |
| 56 | + $res = null; |
| 57 | + foreach( array_slice( $cond, 1 ) as $subcond ) { |
| 58 | + if( is_null( $res ) ) |
| 59 | + $res = self::recCheckCondition( $subcond, $user ); |
| 60 | + else |
| 61 | + $res = ($res xor self::recCheckCondition( $subcond, $user )); |
| 62 | + } |
| 63 | + return $res; |
38 | 64 | } |
39 | 65 | } |
| 66 | + # If we got here, the array presumably does not contain other condi- |
| 67 | + # tions; it's not recursive. Pass it off to self::checkCondition. |
40 | 68 | if( !is_array( $cond ) ) |
41 | 69 | $cond = array( $cond ); |
42 | 70 | return self::checkCondition( $cond, $user ); |
43 | 71 | } |
44 | 72 | |
45 | | - static function checkCondition( $cond, $user ) { |
| 73 | + /** |
| 74 | + * As recCheckCondition, but *not* recursive. The only valid conditions |
| 75 | + * are those whose first element is APCOND_EMAILCONFIRMED/APCOND_EDITCOUNT/ |
| 76 | + * APCOND_AGE. Other types will throw an exception if no extension evalu- |
| 77 | + * ates them. |
| 78 | + * |
| 79 | + * @param array $cond A condition, which must not contain other conditions |
| 80 | + * @param User $user The user to check the condition against |
| 81 | + * @return bool Whether the condition is true for the user |
| 82 | + */ |
| 83 | + private static function checkCondition( $cond, User $user ) { |
46 | 84 | if( count( $cond ) < 1 ) |
47 | 85 | return false; |
48 | 86 | switch( $cond[0] ) { |
49 | 87 | case APCOND_EMAILCONFIRMED: |
50 | 88 | if( User::isValidEmailAddr( $user->getEmail() ) ) { |
| 89 | + # FIXME: EMAILCONFIRMED is always true if |
| 90 | + # wgEmailAuthentication if false, this is confusing. |
51 | 91 | global $wgEmailAuthentication; |
52 | 92 | if( $wgEmailAuthentication ) { |
53 | 93 | return $user->getEmailAuthenticationTimestamp() ? true : false; |
— | — | @@ -56,15 +96,17 @@ |
57 | 97 | } |
58 | 98 | return false; |
59 | 99 | case APCOND_EDITCOUNT: |
60 | | - return $user->getEditCount() > $cond[1]; |
| 100 | + return $user->getEditCount() >= $cond[1]; |
61 | 101 | case APCOND_AGE: |
62 | 102 | $age = time() - wfTimestampOrNull( TS_UNIX, $user->getRegistration() ); |
63 | 103 | return $age >= $cond[1]; |
64 | | - case APCOND_INGROUPS: |
65 | 104 | default: |
66 | | - $result = false; |
| 105 | + $result = null; |
67 | 106 | wfRunHooks( 'AutopromoteCondition', array( $cond[0], array_slice( $cond, 1 ), $user, &$result ) ); |
68 | | - return $result; |
| 107 | + if( $result === null ) { |
| 108 | + throw new MWException( "Unrecognized condition {$cond[0]} for autopromotion!" ); |
| 109 | + } |
| 110 | + return $result ? true : false; |
69 | 111 | } |
70 | 112 | } |
71 | | -} |
\ No newline at end of file |
| 113 | +} |
Index: trunk/phase3/RELEASE-NOTES |
— | — | @@ -34,8 +34,7 @@ |
35 | 35 | any groups they are in. |
36 | 36 | * New permission userrights-interwiki for changing user rights on foreign wikis. |
37 | 37 | * $wgImplictGroups for groups that are hidden from Special:Listusers, etc. |
38 | | -* $wgAutopromote: automatically promote user flags when user matches |
39 | | - criterias |
| 38 | +* $wgAutopromote: automatically promote users who match specified criteria |
40 | 39 | |
41 | 40 | === New features in 1.12 === |
42 | 41 | * (bug 10735) Add a warning for non-descriptive filenames at Special:Upload |