r52083 MediaWiki - Code Review archive

Repository:MediaWiki
Revision:r52082‎ | r52083 | r52084 >
Date:02:50, 18 June 2009
Author:skizzerz
Status:resolved (Comments)
Tags:
Comment:
* Add autopromote condition APCOND_BLOCKED to autopromote blocked users to various user groups.
* Add $wgRemoveGroups as a means of restricting a group's rights. The syntax is identical to $wgGroupPermissions, but users in these groups will have these rights stripped from them.
* Modify Special:ListGroupRights so that it displays revoked permissions as well (the display of assigned vs. revoked is changeable via css).
* Bump $wgStyleVersion
Modified paths:
  • /trunk/phase3/RELEASE-NOTES (modified) (history)
  • /trunk/phase3/includes/Article.php (modified) (history)
  • /trunk/phase3/includes/Autopromote.php (modified) (history)
  • /trunk/phase3/includes/DefaultSettings.php (modified) (history)
  • /trunk/phase3/includes/Defines.php (modified) (history)
  • /trunk/phase3/includes/ProtectionForm.php (modified) (history)
  • /trunk/phase3/includes/User.php (modified) (history)
  • /trunk/phase3/includes/specials/SpecialListgrouprights.php (modified) (history)
  • /trunk/phase3/languages/messages/MessagesEn.php (modified) (history)
  • /trunk/phase3/languages/messages/MessagesQqq.php (modified) (history)
  • /trunk/phase3/skins/common/shared.css (modified) (history)

Diff [purge]

Index: trunk/phase3/skins/common/shared.css
@@ -106,7 +106,7 @@
107107
108108 div.searchresult {
109109 font-size: 95%;
110 - width:38em;
 110+ width:38em;
111111 }
112112
113113 .mw-search-results {
@@ -133,7 +133,7 @@
134134 border: 1px solid silver;
135135 }
136136 .mw-search-formheader div.search-types {
137 - float:left;
 137+ float:left;
138138 padding-left: 0.25em;
139139 }
140140 .mw-search-formheader div.search-types > ul {
@@ -261,7 +261,7 @@
262262 padding-right: 0.15em;
263263 padding-bottom: 0.2em;
264264 padding-top: 0.15em;
265 - background-color:#ececec;
 265+ background-color:#ececec;
266266 border-top:1px solid #BBBBBB;
267267 }
268268
@@ -318,29 +318,29 @@
319319 padding-right: 1.5em;
320320 }
321321
322 -/*
 322+/*
323323 * OpenSearch ajax suggestions
324324 */
325325 .os-suggest {
326 - overflow: auto;
327 - overflow-x: hidden;
 326+ overflow: auto;
 327+ overflow-x: hidden;
328328 position: absolute;
329329 top: 0px;
330330 left: 0px;
331331 width: 0px;
332 - background-color: white;
 332+ background-color: white;
333333 background-color: Window;
334334 border-style: solid;
335335 border-color: #AAAAAA;
336336 border-width: 1px;
337 - z-index:99;
338 - visibility:hidden;
339 - font-size:95%;
 337+ z-index:99;
 338+ visibility:hidden;
 339+ font-size:95%;
340340 }
341341
342342 table.os-suggest-results {
343343 font-size: 95%;
344 - cursor: pointer;
 344+ cursor: pointer;
345345 border: 0;
346346 border-collapse: collapse;
347347 width: 100%;
@@ -348,7 +348,7 @@
349349
350350 td.os-suggest-result, td.os-suggest-result-hl {
351351 white-space: nowrap;
352 - background-color: white;
 352+ background-color: white;
353353 background-color: Window;
354354 color: black;
355355 color: WindowText;
@@ -356,7 +356,7 @@
357357 }
358358 td.os-suggest-result-hl,
359359 td.os-suggest-result-hl-webkit {
360 - background-color: #4C59A6;
 360+ background-color: #4C59A6;
361361 color: white;
362362 }
363363 td.os-suggest-result-hl {
@@ -367,7 +367,7 @@
368368 }
369369
370370 .os-suggest-toggle {
371 - position: relative;
 371+ position: relative;
372372 left: 1ex;
373373 font-size: 65%;
374374 }
@@ -402,6 +402,7 @@
403403 table.mw-listgrouprights-table tr {
404404 vertical-align: top;
405405 }
 406+.listgrouprights-revoked { text-decoration: line-through; }
406407
407408 /* Special:Statistics styling */
408409 td.mw-statistics-numbers {
Index: trunk/phase3/includes/ProtectionForm.php
@@ -38,9 +38,9 @@
3939 /** Map of action to "other" expiry time. Used in preference to mExpirySelection. */
4040 var $mExpiry = array();
4141
42 - /**
43 - * Map of action to value selected in expiry drop-down list.
44 - * Will be set to 'othertime' whenever mExpiry is set.
 42+ /**
 43+ * Map of action to value selected in expiry drop-down list.
 44+ * Will be set to 'othertime' whenever mExpiry is set.
4545 */
4646 var $mExpirySelection = array();
4747
@@ -127,7 +127,7 @@
128128 }
129129 }
130130
131 - /**
 131+ /**
132132 * Get the expiry time for a given action, by combining the relevant inputs.
133133 * Returns a 14-char timestamp or "infinity", or false if the input was invalid
134134 */
@@ -230,7 +230,7 @@
231231 $this->show( wfMsg( 'sessionfailure' ) );
232232 return false;
233233 }
234 -
 234+
235235 # Create reason string. Use list and/or custom string.
236236 $reasonstr = $this->mReasonSelection;
237237 if ( $reasonstr != 'other' && $this->mReason != '' ) {
@@ -296,8 +296,8 @@
297297 $out = '';
298298 if( !$this->disabled ) {
299299 $out .= $this->buildScript();
300 - $out .= Xml::openElement( 'form', array( 'method' => 'post',
301 - 'action' => $this->mTitle->getLocalUrl( 'action=protect' ),
 300+ $out .= Xml::openElement( 'form', array( 'method' => 'post',
 301+ 'action' => $this->mTitle->getLocalUrl( 'action=protect' ),
302302 'id' => 'mw-Protect-Form', 'onsubmit' => 'ProtectionForm.enableUnchainedInputs(true)' ) );
303303 $out .= Xml::hidden( 'wpEditToken',$wgUser->editToken() );
304304 }
@@ -321,7 +321,7 @@
322322
323323 $reasonDropDown = Xml::listDropDown( 'wpProtectReasonSelection',
324324 wfMsgForContent( 'protect-dropdown' ),
325 - wfMsgForContent( 'protect-otherreason-op' ),
 325+ wfMsgForContent( 'protect-otherreason-op' ),
326326 $this->mReasonSelection,
327327 'mwProtect-reason', 4 );
328328 $scExpiryOptions = wfMsgForContent( 'protect-expiry-options' );
@@ -336,14 +336,14 @@
337337 $timestamp = $wgLang->timeanddate( $this->mExistingExpiry[$action] );
338338 $d = $wgLang->date( $this->mExistingExpiry[$action] );
339339 $t = $wgLang->time( $this->mExistingExpiry[$action] );
340 - $expiryFormOptions .=
341 - Xml::option(
 340+ $expiryFormOptions .=
 341+ Xml::option(
342342 wfMsg( 'protect-existing-expiry', $timestamp, $d, $t ),
343343 'existing',
344344 $this->mExpirySelection[$action] == 'existing'
345345 ) . "\n";
346346 }
347 -
 347+
348348 $expiryFormOptions .= Xml::option( wfMsg( 'protect-othertime-op' ), "othertime" ) . "\n";
349349 foreach( explode(',', $scExpiryOptions) as $option ) {
350350 if ( strpos($option, ":") === false ) {
@@ -399,13 +399,13 @@
400400 $out .= '<tr>
401401 <td></td>
402402 <td class="mw-input">' .
403 - Xml::checkLabel( wfMsg( 'protect-cascade' ), 'mwProtect-cascade', 'mwProtect-cascade',
 403+ Xml::checkLabel( wfMsg( 'protect-cascade' ), 'mwProtect-cascade', 'mwProtect-cascade',
404404 $this->mCascade, $this->disabledAttrib ) .
405405 "</td>
406406 </tr>\n";
407407 $out .= Xml::closeElement( 'tbody' ) . Xml::closeElement( 'table' );
408408 }
409 -
 409+
410410 # Add manual and custom reason field/selects as well as submit
411411 if( !$this->disabled ) {
412412 $out .= Xml::openElement( 'table', array( 'id' => 'mw-protect-table3' ) ) .
@@ -424,7 +424,7 @@
425425 {$mProtectreason}
426426 </td>
427427 <td class='mw-input'>" .
428 - Xml::input( 'mwProtect-reason', 60, $this->mReason, array( 'type' => 'text',
 428+ Xml::input( 'mwProtect-reason', 60, $this->mReason, array( 'type' => 'text',
429429 'id' => 'mwProtect-reason', 'maxlength' => 255 ) ) .
430430 "</td>
431431 </tr>
Index: trunk/phase3/includes/Defines.php
@@ -228,3 +228,4 @@
229229 define( 'APCOND_ISIP', 5 );
230230 define( 'APCOND_IPINRANGE', 6 );
231231 define( 'APCOND_AGE_FROM_EDIT', 7 );
 232+define( 'APCOND_BLOCKED', 8 );
Index: trunk/phase3/includes/User.php
@@ -43,7 +43,7 @@
4444 class User {
4545
4646 /**
47 - * \type{\arrayof{\string}} A list of default user toggles, i.e., boolean user
 47+ * \type{\arrayof{\string}} A list of default user toggles, i.e., boolean user
4848 * preferences that are displayed by Special:Preferences as checkboxes.
4949 * This list can be extended via the UserToggles hook or by
5050 * $wgContLang::getExtraUserToggles().
@@ -95,8 +95,8 @@
9696 );
9797
9898 /**
99 - * \type{\arrayof{\string}} List of member variables which are saved to the
100 - * shared cache (memcached). Any operation which changes the
 99+ * \type{\arrayof{\string}} List of member variables which are saved to the
 100+ * shared cache (memcached). Any operation which changes the
101101 * corresponding database fields must call a cache-clearing function.
102102 * @showinitializer
103103 */
@@ -124,7 +124,7 @@
125125
126126 /**
127127 * \type{\arrayof{\string}} Core rights.
128 - * Each of these should have a corresponding message of the form
 128+ * Each of these should have a corresponding message of the form
129129 * "right-$right".
130130 * @showinitializer
131131 */
@@ -211,14 +211,14 @@
212212 /** @name Lazy-initialized variables, invalidated with clearInstanceCache */
213213 //@{
214214 var $mNewtalk, $mDatePreference, $mBlockedby, $mHash, $mSkin, $mRights,
215 - $mBlockreason, $mBlock, $mEffectiveGroups, $mBlockedGlobally,
 215+ $mBlockreason, $mBlock, $mEffectiveGroups, $mBlockedGlobally,
216216 $mLocked, $mHideName, $mOptions;
217217 //@}
218218
219219 /**
220220 * Lightweight constructor for an anonymous user.
221221 * Use the User::newFrom* factory functions for other kinds of users.
222 - *
 222+ *
223223 * @see newFromName()
224224 * @see newFromId()
225225 * @see newFromConfirmationCode()
@@ -325,8 +325,8 @@
326326 global $wgMemc;
327327 $wgMemc->set( $key, $data );
328328 }
329 -
330 -
 329+
 330+
331331 /** @name newFrom*() static factory methods */
332332 //@{
333333
@@ -341,8 +341,8 @@
342342 * User::getCanonicalName(), except that true is accepted as an alias
343343 * for 'valid', for BC.
344344 *
345 - * @return \type{User} The User object, or null if the username is invalid. If the
346 - * username is not present in the database, the result will be a user object
 345+ * @return \type{User} The User object, or null if the username is invalid. If the
 346+ * username is not present in the database, the result will be a user object
347347 * with a name, zero user ID and default settings.
348348 */
349349 static function newFromName( $name, $validate = 'valid' ) {
@@ -420,10 +420,10 @@
421421 $user->loadFromRow( $row );
422422 return $user;
423423 }
424 -
 424+
425425 //@}
426 -
427426
 427+
428428 /**
429429 * Get the username corresponding to a given user ID
430430 * @param $id \int User ID
@@ -661,7 +661,7 @@
662662 return false;
663663
664664 # Clean up name according to title rules
665 - $t = ($validate === 'valid') ?
 665+ $t = ($validate === 'valid') ?
666666 Title::newFromText( $name ) : Title::makeTitle( NS_USER, $name );
667667 # Check for invalid titles
668668 if( is_null( $t ) ) {
@@ -755,9 +755,9 @@
756756 }
757757
758758 /**
759 - * Set cached properties to default.
 759+ * Set cached properties to default.
760760 *
761 - * @note This no longer clears uncached lazy-initialised properties;
 761+ * @note This no longer clears uncached lazy-initialised properties;
762762 * the constructor does that instead.
763763 * @private
764764 */
@@ -819,7 +819,7 @@
820820 $sId = intval( $_COOKIE["{$wgCookiePrefix}UserID"] );
821821 if( isset( $_SESSION['wsUserID'] ) && $sId != $_SESSION['wsUserID'] ) {
822822 $this->loadDefaults(); // Possible collision!
823 - wfDebugLog( 'loginSessions', "Session user ID ({$_SESSION['wsUserID']}) and
 823+ wfDebugLog( 'loginSessions', "Session user ID ({$_SESSION['wsUserID']}) and
824824 cookie user ID ($sId) don't match!" );
825825 return false;
826826 }
@@ -937,7 +937,7 @@
938938 $this->mEmailToken = $row->user_email_token;
939939 $this->mEmailTokenExpires = wfTimestampOrNull( TS_MW, $row->user_email_token_expires );
940940 $this->mRegistration = wfTimestampOrNull( TS_MW, $row->user_registration );
941 - $this->mEditCount = $row->user_editcount;
 941+ $this->mEditCount = $row->user_editcount;
942942 }
943943
944944 /**
@@ -1065,7 +1065,7 @@
10661066 // due to -1 !== 0. Probably session-related... Nothing should be
10671067 // overwriting mBlockedby, surely?
10681068 $this->load();
1069 -
 1069+
10701070 $this->mBlockedby = 0;
10711071 $this->mHideName = 0;
10721072 $this->mAllowUsertalk = 0;
@@ -1089,8 +1089,8 @@
10901090 $this->spreadBlock();
10911091 }
10921092 } else {
1093 - // Bug 13611: don't remove mBlock here, to allow account creation blocks to
1094 - // apply to users. Note that the existence of $this->mBlock is not used to
 1093+ // Bug 13611: don't remove mBlock here, to allow account creation blocks to
 1094+ // apply to users. Note that the existence of $this->mBlock is not used to
10951095 // check for edit blocks, $this->mBlockedby is instead.
10961096 }
10971097
@@ -1275,7 +1275,7 @@
12761276
12771277 /**
12781278 * Check if user is blocked
1279 - *
 1279+ *
12801280 * @param $bFromSlave \bool Whether to check the slave database instead of the master
12811281 * @return \bool True if blocked, false otherwise
12821282 */
@@ -1287,7 +1287,7 @@
12881288
12891289 /**
12901290 * Check if user is blocked from editing a particular article
1291 - *
 1291+ *
12921292 * @param $title \string Title to check
12931293 * @param $bFromSlave \bool Whether to check the slave database instead of the master
12941294 * @return \bool True if blocked, false otherwise
@@ -1327,7 +1327,7 @@
13281328 $this->getBlockedStatus();
13291329 return $this->mBlockreason;
13301330 }
1331 -
 1331+
13321332 /**
13331333 * If user is blocked, return the ID for the block
13341334 * @return \int Block ID
@@ -1336,12 +1336,12 @@
13371337 $this->getBlockedStatus();
13381338 return ($this->mBlock ? $this->mBlock->mId : false);
13391339 }
1340 -
 1340+
13411341 /**
13421342 * Check if user is blocked on all wikis.
13431343 * Do not use for actual edit permission checks!
13441344 * This is intented for quick UI checks.
1345 - *
 1345+ *
13461346 * @param $ip \type{\string} IP address, uses current client if none given
13471347 * @return \type{\bool} True if blocked, false otherwise
13481348 */
@@ -1360,10 +1360,10 @@
13611361 $this->mBlockedGlobally = (bool)$blocked;
13621362 return $this->mBlockedGlobally;
13631363 }
1364 -
 1364+
13651365 /**
13661366 * Check if user account is locked
1367 - *
 1367+ *
13681368 * @return \type{\bool} True if locked, false otherwise
13691369 */
13701370 function isLocked() {
@@ -1375,10 +1375,10 @@
13761376 $this->mLocked = (bool)$authUser->isLocked();
13771377 return $this->mLocked;
13781378 }
1379 -
 1379+
13801380 /**
13811381 * Check if user account is hidden
1382 - *
 1382+ *
13831383 * @return \type{\bool} True if hidden, false otherwise
13841384 */
13851385 function isHidden() {
@@ -1733,7 +1733,7 @@
17341734 $this->mNewpassword = '';
17351735 $this->mNewpassTime = null;
17361736 }
1737 -
 1737+
17381738 /**
17391739 * Get the user's current token.
17401740 * @return \string Token
@@ -1742,7 +1742,7 @@
17431743 $this->load();
17441744 return $this->mToken;
17451745 }
1746 -
 1746+
17471747 /**
17481748 * Set the random token (used for persistent authentication)
17491749 * Called from loadDefaults() among other places.
@@ -1766,7 +1766,7 @@
17671767 $this->mToken = $token;
17681768 }
17691769 }
1770 -
 1770+
17711771 /**
17721772 * Set the cookie password
17731773 *
@@ -1793,7 +1793,7 @@
17941794 }
17951795
17961796 /**
1797 - * Has password reminder email been sent within the last
 1797+ * Has password reminder email been sent within the last
17981798 * $wgPasswordReminderResendTime hours?
17991799 * @return \bool True or false
18001800 */
@@ -1880,7 +1880,7 @@
18811881 return $defaultOverride;
18821882 }
18831883 }
1884 -
 1884+
18851885 /**
18861886 * Get the user's current setting for a given option, as a boolean value.
18871887 *
@@ -1892,7 +1892,7 @@
18931893 return (bool)$this->getOption( $oname );
18941894 }
18951895
1896 -
 1896+
18971897 /**
18981898 * Get the user's current setting for a given option, as a boolean value.
18991899 *
@@ -1932,10 +1932,10 @@
19331933
19341934 $this->mOptions[$oname] = $val;
19351935 }
1936 -
 1936+
19371937 /**
19381938 * Reset all options to the site defaults
1939 - */
 1939+ */
19401940 function resetOptions() {
19411941 $this->mOptions = User::getDefaultOptions();
19421942 }
@@ -2112,7 +2112,7 @@
21132113 if( !$wgUseRCPatrol && !$wgUseNPPatrol )
21142114 return false;
21152115 }
2116 - # Use strict parameter to avoid matching numeric 0 accidentally inserted
 2116+ # Use strict parameter to avoid matching numeric 0 accidentally inserted
21172117 # by misconfiguration: 0 == 'foo'
21182118 return in_array( $action, $this->getRights(), true );
21192119 }
@@ -2156,7 +2156,7 @@
21572157 global $wgDefaultSkin;
21582158 $userSkin = $wgDefaultSkin;
21592159 }
2160 -
 2160+
21612161 $this->mSkin =& Skin::newFromKey( $userSkin );
21622162 wfProfileOut( __METHOD__ );
21632163 }
@@ -2309,20 +2309,20 @@
23102310 }
23112311 }
23122312 }
2313 -
 2313+
23142314 /**
2315 - * Set a cookie on the user's client. Wrapper for
 2315+ * Set a cookie on the user's client. Wrapper for
23162316 * WebResponse::setCookie
23172317 * @param $name \string Name of the cookie to set
23182318 * @param $value \string Value to set
2319 - * @param $exp \int Expiration time, as a UNIX time value;
 2319+ * @param $exp \int Expiration time, as a UNIX time value;
23202320 * if 0 or not specified, use the default $wgCookieExpiration
23212321 */
23222322 protected function setCookie( $name, $value, $exp=0 ) {
23232323 global $wgRequest;
23242324 $wgRequest->response()->setcookie( $name, $value, $exp );
23252325 }
2326 -
 2326+
23272327 /**
23282328 * Clear a cookie on the user's client
23292329 * @param $name \string Name of the cookie to clear
@@ -2337,7 +2337,7 @@
23382338 function setCookies() {
23392339 $this->load();
23402340 if ( 0 == $this->mId ) return;
2341 - $session = array(
 2341+ $session = array(
23422342 'wsUserID' => $this->mId,
23432343 'wsToken' => $this->mToken,
23442344 'wsUserName' => $this->getName()
@@ -2351,9 +2351,9 @@
23522352 } else {
23532353 $cookies['Token'] = false;
23542354 }
2355 -
 2355+
23562356 wfRunHooks( 'UserSetCookies', array( $this, &$session, &$cookies ) );
2357 - #check for null, since the hook could cause a null value
 2357+ #check for null, since the hook could cause a null value
23582358 if ( !is_null( $session ) && isset( $_SESSION ) ){
23592359 $_SESSION = $session + $_SESSION;
23602360 }
@@ -2669,27 +2669,27 @@
26702670 function isNewbie() {
26712671 return !$this->isAllowed( 'autoconfirmed' );
26722672 }
2673 -
 2673+
26742674 /**
26752675 * Is the user active? We check to see if they've made at least
26762676 * X number of edits in the last Y days.
2677 - *
 2677+ *
26782678 * @return \bool True if the user is active, false if not.
26792679 */
26802680 public function isActiveEditor() {
26812681 global $wgActiveUserEditCount, $wgActiveUserDays;
26822682 $dbr = wfGetDB( DB_SLAVE );
2683 -
 2683+
26842684 // Stolen without shame from RC
26852685 $cutoff_unixtime = time() - ( $wgActiveUserDays * 86400 );
26862686 $cutoff_unixtime = $cutoff_unixtime - ( $cutoff_unixtime % 86400 );
26872687 $oldTime = $dbr->addQuotes( $dbr->timestamp( $cutoff_unixtime ) );
2688 -
 2688+
26892689 $res = $dbr->select( 'revision', '1',
26902690 array( 'rev_user_text' => $this->getName(), "rev_timestamp > $oldTime"),
26912691 __METHOD__,
26922692 array('LIMIT' => $wgActiveUserEditCount ) );
2693 -
 2693+
26942694 $count = $dbr->numRows($res);
26952695 $dbr->freeResult($res);
26962696
@@ -2833,7 +2833,7 @@
28342834 $url = $this->confirmationTokenUrl( $token );
28352835 $invalidateURL = $this->invalidationTokenUrl( $token );
28362836 $this->saveSettings();
2837 -
 2837+
28382838 return $this->sendMail( wfMsg( 'confirmemail_subject' ),
28392839 wfMsg( 'confirmemail_body',
28402840 wfGetIP(),
@@ -2907,7 +2907,7 @@
29082908 function invalidationTokenUrl( $token ) {
29092909 return $this->getTokenUrl( 'Invalidateemail', $token );
29102910 }
2911 -
 2911+
29122912 /**
29132913 * Internal function to format the e-mail validation/invalidation URLs.
29142914 * This uses $wgArticlePath directly as a quickie hack to use the
@@ -3039,7 +3039,7 @@
30403040 ? $this->mRegistration
30413041 : false;
30423042 }
3043 -
 3043+
30443044 /**
30453045 * Get the timestamp of the first edit
30463046 *
@@ -3056,7 +3056,7 @@
30573057 );
30583058 if( !$time ) return false; // no edits
30593059 return wfTimestamp( TS_MW, $time );
3060 - }
 3060+ }
30613061
30623062 /**
30633063 * Get the permissions associated with a given list of groups
@@ -3065,7 +3065,7 @@
30663066 * @return \type{\arrayof{\string}} List of permission key names for given groups combined
30673067 */
30683068 static function getGroupPermissions( $groups ) {
3069 - global $wgGroupPermissions;
 3069+ global $wgGroupPermissions, $wgRevokePermissions;
30703070 $rights = array();
30713071 foreach( $groups as $group ) {
30723072 if( isset( $wgGroupPermissions[$group] ) ) {
@@ -3073,13 +3073,17 @@
30743074 // array_filter removes empty items
30753075 array_keys( array_filter( $wgGroupPermissions[$group] ) ) );
30763076 }
 3077+ if( isset( $wgRevokePermissions[$group] ) ) {
 3078+ $rights = array_diff( $rights,
 3079+ array_keys( array_filter( $wgRevokePermissions[$group] ) ) );
 3080+ }
30773081 }
30783082 return array_unique($rights);
30793083 }
3080 -
 3084+
30813085 /**
30823086 * Get all the groups who have a given permission
3083 - *
 3087+ *
30843088 * @param $role \string Role to check
30853089 * @return \type{\arrayof{\string}} List of internal group names with the given permission
30863090 */
@@ -3133,9 +3137,9 @@
31343138 * @return \type{\arrayof{\string}} Array of internal group names
31353139 */
31363140 static function getAllGroups() {
3137 - global $wgGroupPermissions;
 3141+ global $wgGroupPermissions, $wgRevokePermissions;
31383142 return array_diff(
3139 - array_keys( $wgGroupPermissions ),
 3143+ array_merge( array_keys( $wgGroupPermissions ), array_keys( $wgRevokePermissions ) ),
31403144 self::getImplicitGroups()
31413145 );
31423146 }
@@ -3187,7 +3191,7 @@
31883192 }
31893193
31903194 /**
3191 - * Create a link to the group in HTML, if available;
 3195+ * Create a link to the group in HTML, if available;
31923196 * else return the group name.
31933197 *
31943198 * @param $group \string Internal name of the group
@@ -3209,7 +3213,7 @@
32103214 }
32113215
32123216 /**
3213 - * Create a link to the group in Wikitext, if available;
 3217+ * Create a link to the group in Wikitext, if available;
32143218 * else return the group name.
32153219 *
32163220 * @param $group \string Internal name of the group
@@ -3228,7 +3232,7 @@
32293233 return $text;
32303234 }
32313235 }
3232 -
 3236+
32333237 /**
32343238 * Returns an array of the groups that a particular group can add/remove.
32353239 *
@@ -3258,7 +3262,7 @@
32593263 } elseif( is_array($wgRemoveGroups[$group]) ) {
32603264 $groups['remove'] = $wgRemoveGroups[$group];
32613265 }
3262 -
 3266+
32633267 // Re-map numeric keys of AddToSelf/RemoveFromSelf to the 'user' key for backwards compatibility
32643268 if( empty($wgGroupsAddToSelf['user']) || $wgGroupsAddToSelf['user'] !== true ) {
32653269 foreach($wgGroupsAddToSelf as $key => $value) {
@@ -3267,7 +3271,7 @@
32683272 }
32693273 }
32703274 }
3271 -
 3275+
32723276 if( empty($wgGroupsRemoveFromSelf['user']) || $wgGroupsRemoveFromSelf['user'] !== true ) {
32733277 foreach($wgGroupsRemoveFromSelf as $key => $value) {
32743278 if( is_int($key) ) {
@@ -3275,7 +3279,7 @@
32763280 }
32773281 }
32783282 }
3279 -
 3283+
32803284 // Now figure out what groups the user can add to him/herself
32813285 if( empty($wgGroupsAddToSelf[$group]) ) {
32823286 } elseif( $wgGroupsAddToSelf[$group] === true ) {
@@ -3284,17 +3288,17 @@
32853289 } elseif( is_array($wgGroupsAddToSelf[$group]) ) {
32863290 $groups['add-self'] = $wgGroupsAddToSelf[$group];
32873291 }
3288 -
 3292+
32893293 if( empty($wgGroupsRemoveFromSelf[$group]) ) {
32903294 } elseif( $wgGroupsRemoveFromSelf[$group] === true ) {
32913295 $groups['remove-self'] = User::getAllGroups();
32923296 } elseif( is_array($wgGroupsRemoveFromSelf[$group]) ) {
32933297 $groups['remove-self'] = $wgGroupsRemoveFromSelf[$group];
32943298 }
3295 -
 3299+
32963300 return $groups;
32973301 }
3298 -
 3302+
32993303 /**
33003304 * Returns an array of groups that this user can add and remove
33013305 * @return Array array( 'add' => array( addablegroups ),
@@ -3380,7 +3384,7 @@
33813385 // edit count in user cache too
33823386 $this->invalidateCache();
33833387 }
3384 -
 3388+
33853389 /**
33863390 * Get the description of a given right
33873391 *
@@ -3417,7 +3421,7 @@
34183422 * Make a new-style password hash
34193423 *
34203424 * @param $password \string Plain-text password
3421 - * @param $salt \string Optional salt, may be random or the user ID.
 3425+ * @param $salt \string Optional salt, may be random or the user ID.
34223426 * If unspecified or false, will generate one automatically
34233427 * @return \string Password hash
34243428 */
@@ -3428,7 +3432,7 @@
34293433 if( !wfRunHooks( 'UserCryptPassword', array( &$password, &$salt, &$wgPasswordSalt, &$hash ) ) ) {
34303434 return $hash;
34313435 }
3432 -
 3436+
34333437 if( $wgPasswordSalt ) {
34343438 if ( $salt === false ) {
34353439 $salt = substr( wfGenerateToken(), 0, 8 );
@@ -3451,12 +3455,12 @@
34523456 static function comparePasswords( $hash, $password, $userId = false ) {
34533457 $m = false;
34543458 $type = substr( $hash, 0, 3 );
3455 -
 3459+
34563460 $result = false;
34573461 if( !wfRunHooks( 'UserComparePasswords', array( &$hash, &$password, &$userId, &$result ) ) ) {
34583462 return $result;
34593463 }
3460 -
 3464+
34613465 if ( $type == ':A:' ) {
34623466 # Unsalted
34633467 return md5( $password ) === substr( $hash, 3 );
@@ -3469,7 +3473,7 @@
34703474 return self::oldCrypt( $password, $userId ) === $hash;
34713475 }
34723476 }
3473 -
 3477+
34743478 /**
34753479 * Add a newuser log entry for this user
34763480 * @param $byEmail Boolean: account made by email?
Index: trunk/phase3/includes/Article.php
@@ -108,7 +108,7 @@
109109 return null;
110110 }
111111 $dbw = wfGetDB( DB_MASTER );
112 - $dbw->replace( 'redirect', array('rd_from'),
 112+ $dbw->replace( 'redirect', array('rd_from'),
113113 array(
114114 'rd_from' => $this->getID(),
115115 'rd_namespace' => $retval->getNamespace(),
@@ -228,7 +228,7 @@
229229 return $this->mContent;
230230 }
231231 }
232 -
 232+
233233 /**
234234 * Get the text of the current revision. No side-effects...
235235 *
@@ -260,12 +260,12 @@
261261 global $wgParser;
262262 return $wgParser->getSection( $text, $section );
263263 }
264 -
 264+
265265 /**
266266 * Get the text that needs to be saved in order to undo all revisions
267267 * between $undo and $undoafter. Revisions must belong to the same page,
268268 * must exist and must not be deleted
269 - * @param $undo Revision
 269+ * @param $undo Revision
270270 * @param $undoafter Revision Must be an earlier revision than $undo
271271 * @return mixed string on success, false on failure
272272 */
@@ -545,7 +545,7 @@
546546 public function exists() {
547547 return $this->getId() > 0;
548548 }
549 -
 549+
550550 /**
551551 * Check if this page is something we're going to be showing
552552 * some sort of sensible content for. If we return false, page
@@ -568,10 +568,10 @@
569569 $this->mCounter = 0;
570570 } else {
571571 $dbr = wfGetDB( DB_SLAVE );
572 - $this->mCounter = $dbr->selectField( 'page',
573 - 'page_counter',
574 - array( 'page_id' => $id ),
575 - __METHOD__,
 572+ $this->mCounter = $dbr->selectField( 'page',
 573+ 'page_counter',
 574+ array( 'page_id' => $id ),
 575+ __METHOD__,
576576 $this->getSelectOptions()
577577 );
578578 }
@@ -731,7 +731,7 @@
732732 if( $wgOut->isPrintable() ) {
733733 $wgOut->parserOptions()->setIsPrintable( true );
734734 }
735 -
 735+
736736 wfProfileIn( __METHOD__ );
737737
738738 # Get variables from query string
@@ -813,7 +813,7 @@
814814 wfProfileOut( __METHOD__ );
815815 return;
816816 }
817 -
 817+
818818 if( $ns == NS_USER || $ns == NS_USER_TALK ) {
819819 # User/User_talk subpages are not modified. (bug 11443)
820820 if( !$this->mTitle->isSubpage() ) {
@@ -907,7 +907,7 @@
908908 $text = wfMsgExt( 'noarticletext', 'parsemag' );
909909 }
910910 }
911 -
 911+
912912 # Non-existent pages
913913 if( $this->getID() === 0 ) {
914914 $wgOut->setRobotPolicy( 'noindex,nofollow' );
@@ -931,7 +931,7 @@
932932 wfProfileOut( __METHOD__ );
933933 return;
934934 }
935 -
 935+
936936 # For ?curid=x urls, disallow indexing
937937 if( $wgRequest->getInt('curid') )
938938 $wgOut->setRobotPolicy( 'noindex,follow' );
@@ -1074,7 +1074,7 @@
10751075 $this->viewUpdates();
10761076 wfProfileOut( __METHOD__ );
10771077 }
1078 -
 1078+
10791079 protected function showLogs() {
10801080 global $wgUser, $wgOut;
10811081 $loglist = new LogEventsList( $wgUser->getSkin(), $wgOut );
@@ -1094,7 +1094,7 @@
10951095 SpecialPage::getTitleFor( 'Log' ),
10961096 wfMsgHtml( 'log-fulllog' ),
10971097 array(),
1098 - array( 'page' => $this->mTitle->getPrefixedText() )
 1098+ array( 'page' => $this->mTitle->getPrefixedText() )
10991099 ) );
11001100 }
11011101 $wgOut->addHTML( '</div>' );
@@ -1131,7 +1131,7 @@
11321132 $imageUrl = $wgStylePath . '/common/images/redirect' . $imageDir . '.png';
11331133 $imageUrl2 = $wgStylePath . '/common/images/nextredirect' . $imageDir . '.png';
11341134 $alt2 = $wgContLang->isRTL() ? '&larr;' : '&rarr;'; // should -> and <- be used instead of entities?
1135 -
 1135+
11361136 if( $appendSubtitle ) {
11371137 $wgOut->appendSubtitle( wfMsgHtml( 'redirectpagesub' ) );
11381138 }
@@ -1570,9 +1570,9 @@
15711571 * Fill in blank summaries with generated text where possible
15721572 *
15731573 * If neither EDIT_NEW nor EDIT_UPDATE is specified, the status of the article will be detected.
1574 - * If EDIT_UPDATE is specified and the article doesn't exist, the function will an
1575 - * edit-gone-missing error. If EDIT_NEW is specified and the article does exist, an
1576 - * edit-already-exists error will be returned. These two conditions are also possible with
 1574+ * If EDIT_UPDATE is specified and the article doesn't exist, the function will an
 1575+ * edit-gone-missing error. If EDIT_NEW is specified and the article does exist, an
 1576+ * edit-already-exists error will be returned. These two conditions are also possible with
15771577 * auto-detection due to MediaWiki's performance-optimised locking strategy.
15781578 *
15791579 * @param $baseRevId the revision ID this edit was based off, if any
@@ -1607,7 +1607,7 @@
16081608 $status = Status::newGood( array() );
16091609
16101610 # Load $this->mTitle->getArticleID() and $this->mLatest if it's not already
1611 - $this->loadPageData();
 1611+ $this->loadPageData();
16121612
16131613 if( !($flags & EDIT_NEW) && !($flags & EDIT_UPDATE) ) {
16141614 $aid = $this->mTitle->getArticleID();
@@ -1688,9 +1688,9 @@
16891689
16901690 # Update page
16911691 #
1692 - # Note that we use $this->mLatest instead of fetching a value from the master DB
1693 - # during the course of this function. This makes sure that EditPage can detect
1694 - # edit conflicts reliably, either by $ok here, or by $article->getTimestamp()
 1692+ # Note that we use $this->mLatest instead of fetching a value from the master DB
 1693+ # during the course of this function. This makes sure that EditPage can detect
 1694+ # edit conflicts reliably, either by $ok here, or by $article->getTimestamp()
16951695 # before this function is called. A previous function used a separate query, this
16961696 # creates a window where concurrent edits can cause an ignored edit conflict.
16971697 $ok = $this->updateRevisionOn( $dbw, $revision, $this->mLatest );
@@ -1883,12 +1883,12 @@
18841884 $wgOut->showErrorPage( 'rcpatroldisabled', 'rcpatroldisabledtext' );
18851885 return;
18861886 }
1887 -
 1887+
18881888 if( in_array(array('hookaborted'), $errors) ) {
18891889 // The hook itself has handled any output
18901890 return;
18911891 }
1892 -
 1892+
18931893 if( in_array(array('markedaspatrollederror-noautopatrol'), $errors) ) {
18941894 $wgOut->setPageTitle( wfMsg( 'markedaspatrollederror' ) );
18951895 $wgOut->addWikiMsg( 'markedaspatrollederror-noautopatrol' );
@@ -2014,12 +2014,12 @@
20152015 wfDebug( "updateRestrictions failed: $id <= 0\n" );
20162016 return false;
20172017 }
2018 -
 2018+
20192019 if ( wfReadOnly() ) {
20202020 wfDebug( "updateRestrictions failed: read-only\n" );
20212021 return false;
20222022 }
2023 -
 2023+
20242024 if ( !$this->mTitle->userCan( 'protect' ) ) {
20252025 wfDebug( "updateRestrictions failed: insufficient permissions\n" );
20262026 return false;
@@ -2064,7 +2064,7 @@
20652065 if( wfRunHooks( 'ArticleProtect', array( &$this, &$wgUser, $limit, $reason ) ) ) {
20662066
20672067 $dbw = wfGetDB( DB_MASTER );
2068 -
 2068+
20692069 # Prepare a null revision to be added to the history
20702070 $modified = $current != '' && $protect;
20712071 if( $protect ) {
@@ -2080,9 +2080,9 @@
20812081 # The schema allows multiple restrictions
20822082 if(!in_array('protect', $editrestriction) && !in_array('sysop', $editrestriction))
20832083 $cascade = false;
2084 - $cascade_description = '';
 2084+ $cascade_description = '';
20852085 if( $cascade ) {
2086 - $cascade_description = ' ['.wfMsgForContent('protect-summary-cascade').']';
 2086+ $cascade_description = ' ['.wfMsgForContent('protect-summary-cascade').']';
20872087 }
20882088
20892089 if( $reason )
@@ -2094,15 +2094,15 @@
20952095 foreach( $limit as $action => $restrictions ) {
20962096 if ( !isset($expiry[$action]) )
20972097 $expiry[$action] = 'infinite';
2098 -
 2098+
20992099 $encodedExpiry[$action] = Block::encodeExpiry($expiry[$action], $dbw );
21002100 if( $restrictions != '' ) {
21012101 $protect_description .= "[$action=$restrictions] (";
21022102 if( $encodedExpiry[$action] != 'infinity' ) {
2103 - $protect_description .= wfMsgForContent( 'protect-expiring',
 2103+ $protect_description .= wfMsgForContent( 'protect-expiring',
21042104 $wgContLang->timeanddate( $expiry[$action], false, false ) ,
21052105 $wgContLang->date( $expiry[$action], false, false ) ,
2106 - $wgContLang->time( $expiry[$action], false, false ) );
 2106+ $wgContLang->time( $expiry[$action], false, false ) );
21072107 } else {
21082108 $protect_description .= wfMsgForContent( 'protect-expiry-indefinite' );
21092109 }
@@ -2110,7 +2110,7 @@
21112111 }
21122112 }
21132113 $protect_description = trim($protect_description);
2114 -
 2114+
21152115 if( $protect_description && $protect )
21162116 $editComment .= " ($protect_description)";
21172117 if( $cascade )
@@ -2119,9 +2119,9 @@
21202120 foreach( $limit as $action => $restrictions ) {
21212121 if($restrictions != '' ) {
21222122 $dbw->replace( 'page_restrictions', array(array('pr_page', 'pr_type')),
2123 - array( 'pr_page' => $id,
2124 - 'pr_type' => $action,
2125 - 'pr_level' => $restrictions,
 2123+ array( 'pr_page' => $id,
 2124+ 'pr_type' => $action,
 2125+ 'pr_level' => $restrictions,
21262126 'pr_cascade' => ($cascade && $action == 'edit') ? 1 : 0,
21272127 'pr_expiry' => $encodedExpiry[$action] ), __METHOD__ );
21282128 } else {
@@ -2219,7 +2219,7 @@
22202220 if( $res === false )
22212221 // This page has no revisions, which is very weird
22222222 return false;
2223 -
 2223+
22242224 $hasHistory = ( $res->numRows() > 1 );
22252225 $row = $dbw->fetchObject( $res );
22262226 $onlyAuthor = $row->rev_user_text;
@@ -2243,7 +2243,7 @@
22442244 else
22452245 $reason = wfMsgForContent( 'excontent', '$1' );
22462246 }
2247 -
 2247+
22482248 if( $reason == '-' ) {
22492249 // Allow these UI messages to be blanked out cleanly
22502250 return '';
@@ -2454,7 +2454,7 @@
24552455 }
24562456 $checkWatch = $wgUser->getBoolOption( 'watchdeletion' ) || $this->mTitle->userIsWatching();
24572457
2458 - $form = Xml::openElement( 'form', array( 'method' => 'post',
 2458+ $form = Xml::openElement( 'form', array( 'method' => 'post',
24592459 'action' => $this->mTitle->getLocalURL( 'action=delete' ), 'id' => 'deleteconfirm' ) ) .
24602460 Xml::openElement( 'fieldset', array( 'id' => 'mw-delete-table' ) ) .
24612461 Xml::tags( 'legend', null, wfMsgExt( 'delete-legend', array( 'parsemag', 'escapenoentities' ) ) ) .
@@ -2474,7 +2474,7 @@
24752475 Xml::label( wfMsg( 'deleteotherreason' ), 'wpReason' ) .
24762476 "</td>
24772477 <td class='mw-input'>" .
2478 - Xml::input( 'wpReason', 60, $reason, array( 'type' => 'text', 'maxlength' => '255',
 2478+ Xml::input( 'wpReason', 60, $reason, array( 'type' => 'text', 'maxlength' => '255',
24792479 'tabindex' => '2', 'id' => 'wpReason' ) ) .
24802480 "</td>
24812481 </tr>
@@ -2624,7 +2624,7 @@
26252625 $dbw->rollback();
26262626 return false;
26272627 }
2628 -
 2628+
26292629 # Fix category table counts
26302630 $cats = array();
26312631 $res = $dbw->select( 'categorylinks', 'cl_to', array( 'cl_from' => $id ), __METHOD__ );
@@ -2654,7 +2654,7 @@
26552655 if( !$dbw->cleanupTriggers() ) {
26562656 # Clean up recentchanges entries...
26572657 $dbw->delete( 'recentchanges',
2658 - array( 'rc_type != '.RC_LOG,
 2658+ array( 'rc_type != '.RC_LOG,
26592659 'rc_namespace' => $this->mTitle->getNamespace(),
26602660 'rc_title' => $this->mTitle->getDBkey() ),
26612661 __METHOD__ );
@@ -2865,7 +2865,7 @@
28662866 if( isset( $details['current'] ) ){
28672867 $current = $details['current'];
28682868 if( $current->getComment() != '' ) {
2869 - $wgOut->addWikiMsgArray( 'editcomment', array(
 2869+ $wgOut->addWikiMsgArray( 'editcomment', array(
28702870 $wgUser->getSkin()->formatComment( $current->getComment() ) ), array( 'replaceafter' ) );
28712871 }
28722872 }
@@ -2989,7 +2989,7 @@
29902990 # Update the links tables
29912991 $u = new LinksUpdate( $this->mTitle, $editInfo->output );
29922992 $u->doUpdate();
2993 -
 2993+
29942994 wfRunHooks( 'ArticleEditUpdates', array( &$this, &$editInfo, $changed ) );
29952995
29962996 if( wfRunHooks( 'ArticleEditUpdatesDeleteFromRecentchanges', array( &$this ) ) ) {
Index: trunk/phase3/includes/DefaultSettings.php
@@ -226,7 +226,7 @@
227227 * equivalent to the corresponding member of $wgDBservers
228228 * tablePrefix Table prefix, the foreign wiki's $wgDBprefix
229229 * hasSharedCache True if the wiki's shared cache is accessible via the local $wgMemc
230 - *
 230+ *
231231 * ForeignAPIRepo:
232232 * apibase Use for the foreign API's URL
233233 * apiThumbCacheExpiry How long to locally cache thumbs for
@@ -739,7 +739,7 @@
740740 $wgSessionsInMemcached = false;
741741
742742 /** This is used for setting php's session.save_handler. In practice, you will
743 - * almost never need to change this ever. Other options might be 'user' or
 743+ * almost never need to change this ever. Other options might be 'user' or
744744 * 'session_mysql.' Setting to null skips setting this entirely (which might be
745745 * useful if you're doing cross-application sessions, see bug 11381) */
746746 $wgSessionHandler = 'files';
@@ -793,7 +793,7 @@
794794
795795 /**
796796 * Locale for LC_CTYPE, to work around http://bugs.php.net/bug.php?id=45132
797 - * For Unix-like operating systems, set this to to a locale that has a UTF-8
 797+ * For Unix-like operating systems, set this to to a locale that has a UTF-8
798798 * character set. Only the character set is relevant.
799799 */
800800 $wgShellLocale = 'en_US.utf8';
@@ -980,11 +980,11 @@
981981 $wgSiteSupportPage = ''; # A page where you users can receive donations
982982
983983 /**
984 - * Set this to a string to put the wiki into read-only mode. The text will be
985 - * used as an explanation to users.
 984+ * Set this to a string to put the wiki into read-only mode. The text will be
 985+ * used as an explanation to users.
986986 *
987 - * This prevents most write operations via the web interface. Cache updates may
988 - * still be possible. To prevent database writes completely, use the read_only
 987+ * This prevents most write operations via the web interface. Cache updates may
 988+ * still be possible. To prevent database writes completely, use the read_only
989989 * option in MySQL.
990990 */
991991 $wgReadOnly = null;
@@ -999,7 +999,7 @@
10001000 /**
10011001 * Filename for debug logging. See http://www.mediawiki.org/wiki/How_to_debug
10021002 * The debug log file should be not be publicly accessible if it is used, as it
1003 - * may contain private data.
 1003+ * may contain private data.
10041004 */
10051005 $wgDebugLogFile = '';
10061006
@@ -1009,14 +1009,14 @@
10101010 $wgDebugLogPrefix = '';
10111011
10121012 /**
1013 - * If true, instead of redirecting, show a page with a link to the redirect
 1013+ * If true, instead of redirecting, show a page with a link to the redirect
10141014 * destination. This allows for the inspection of PHP error messages, and easy
10151015 * resubmission of form data. For developer use only.
10161016 */
10171017 $wgDebugRedirects = false;
10181018
10191019 /**
1020 - * If true, log debugging data from action=raw.
 1020+ * If true, log debugging data from action=raw.
10211021 * This is normally false to avoid overlapping debug entries due to gen=css and
10221022 * gen=js requests.
10231023 */
@@ -1027,7 +1027,7 @@
10281028 *
10291029 * This may occasionally be useful when supporting a non-technical end-user. It's
10301030 * more secure than exposing the debug log file to the web, since the output only
1031 - * contains private data for the current user. But it's not ideal for development
 1031+ * contains private data for the current user. But it's not ideal for development
10321032 * use since data is lost on fatal errors and redirects.
10331033 */
10341034 $wgDebugComments = false;
@@ -1104,7 +1104,7 @@
11051105 * same options.
11061106 *
11071107 * This can provide a significant speedup for medium to large pages,
1108 - * so you probably want to keep it on. Extensions that conflict with the
 1108+ * so you probably want to keep it on. Extensions that conflict with the
11091109 * parser cache should disable the cache on a per-page basis instead.
11101110 */
11111111 $wgEnableParserCache = true;
@@ -1293,6 +1293,15 @@
12941294 */
12951295 # $wgGroupPermissions['developer']['siteadmin'] = true;
12961296
 1297+/**
 1298+ * Permission keys revoked from users in each group.
 1299+ * This acts the same way as wgGroupPermissions above, except that
 1300+ * if the user is in a group here, the permission will be removed from them.
 1301+ *
 1302+ * Improperly setting this could mean that your users will be unable to perform
 1303+ * certain essential tasks, so use at your own risk!
 1304+ */
 1305+$wgRevokePermissions = array();
12971306
12981307 /**
12991308 * Implicit groups, aren't shown on Special:Listusers or somewhere else
@@ -1304,7 +1313,7 @@
13051314 * are allowed to add or revoke.
13061315 *
13071316 * Setting the list of groups to add or revoke to true is equivalent to "any group".
1308 - *
 1317+ *
13091318 * For example, to allow sysops to add themselves to the "bot" group:
13101319 *
13111320 * $wgGroupsAddToSelf = array( 'sysop' => array( 'bot' ) );
@@ -1315,7 +1324,7 @@
13161325 *
13171326 * This allows users in the '*' group (i.e. any user) to remove themselves from
13181327 * any group that they happen to be in.
1319 - *
 1328+ *
13201329 */
13211330 $wgGroupsAddToSelf = array();
13221331 $wgGroupsRemoveFromSelf = array();
@@ -1389,6 +1398,7 @@
13901399 * array( APCOND_ISIP, ip ), *OR*
13911400 * array( APCOND_IPINRANGE, range ), *OR*
13921401 * array( APCOND_AGE_FROM_EDIT, seconds since first edit ), *OR*
 1402+ * array( APCOND_BLOCKED ), *OR*
13931403 * similar constructs defined by extensions.
13941404 *
13951405 * If $wgEmailAuthentication is off, APCOND_EMAILCONFIRMED will be true for any
@@ -1486,7 +1496,7 @@
14871497 * to ensure that client-side caches do not keep obsolete copies of global
14881498 * styles.
14891499 */
1490 -$wgStyleVersion = '226';
 1500+$wgStyleVersion = '227';
14911501
14921502
14931503 # Server-side caching:
@@ -1709,7 +1719,7 @@
17101720 * Or false to disable it
17111721 */
17121722 $wgEnableImageWhitelist = true;
1713 -
 1723+
17141724 /** Allows to move images and other media files */
17151725 $wgAllowImageMoving = true;
17161726
@@ -1986,13 +1996,13 @@
19871997 );
19881998
19891999 /**
1990 - * Namespaces to be searched when user clicks the "Help" tab
 2000+ * Namespaces to be searched when user clicks the "Help" tab
19912001 * on Special:Search
1992 - *
 2002+ *
19932003 * Same format as $wgNamespacesToBeSearchedDefault
1994 - */
 2004+ */
19952005 $wgNamespacesToBeSearchedHelp = array(
1996 - NS_PROJECT => true,
 2006+ NS_PROJECT => true,
19972007 NS_HELP => true,
19982008 );
19992009
@@ -2055,8 +2065,8 @@
20562066 /** Reduction in linear dimensions below which sharpening will be enabled */
20572067 $wgSharpenReductionThreshold = 0.85;
20582068
2059 -/**
2060 - * Temporary directory used for ImageMagick. The directory must exist. Leave
 2069+/**
 2070+ * Temporary directory used for ImageMagick. The directory must exist. Leave
20612071 * this set to false to let ImageMagick decide for itself.
20622072 */
20632073 $wgImageMagickTempDir = false;
@@ -2196,19 +2206,19 @@
21972207 /**
21982208 * Prefix to prepend to each UDP packet.
21992209 * This can be used to identify the wiki. A script is available called
2200 - * mxircecho.py which listens on a UDP port, and uses a prefix ending in a
 2210+ * mxircecho.py which listens on a UDP port, and uses a prefix ending in a
22012211 * tab to identify the IRC channel to send the log line to.
22022212 */
22032213 $wgRC2UDPPrefix = '';
22042214
22052215 /**
2206 - * If this is set to true, $wgLocalInterwiki will be prepended to links in the
 2216+ * If this is set to true, $wgLocalInterwiki will be prepended to links in the
22072217 * IRC feed. If this is set to a string, that string will be used as the prefix.
22082218 */
22092219 $wgRC2UDPInterwikiPrefix = false;
22102220
22112221 /**
2212 - * Set to true to omit "bot" edits (by users with the bot permission) from the
 2222+ * Set to true to omit "bot" edits (by users with the bot permission) from the
22132223 * UDP feed.
22142224 */
22152225 $wgRC2UDPOmitBots = false;
@@ -2514,8 +2524,8 @@
25152525 'disablemail' => 0,
25162526 );
25172527
2518 -/**
2519 - * Whether or not to allow and use real name fields.
 2528+/**
 2529+ * Whether or not to allow and use real name fields.
25202530 * @deprecated in 1.16, use $wgHiddenPrefs[] = 'realname' below to disable real
25212531 * names
25222532 */
@@ -2926,7 +2936,7 @@
29272937 *
29282938 * This is associative array of log type => boolean "hide by default"
29292939 *
2930 - * See $wgLogTypes for a list of available log types.
 2940+ * See $wgLogTypes for a list of available log types.
29312941 *
29322942 * For example:
29332943 * $wgFilterLogTypes => array(
@@ -2935,7 +2945,7 @@
29362946 * );
29372947 *
29382948 * Will display show/hide links for the move and import logs. Move logs will be
2939 - * hidden by default unless the link is clicked. Import logs will be shown by
 2949+ * hidden by default unless the link is clicked. Import logs will be shown by
29402950 * default, and hidden when the link is clicked.
29412951 *
29422952 * A message of the form log-show-hide-<type> should be added, and will be used
@@ -3733,7 +3743,7 @@
37343744
37353745 /**
37363746 * Fix double redirects after a page move.
3737 - * Tends to conflict with page move vandalism, use only on a private wiki.
 3747+ * Tends to conflict with page move vandalism, use only on a private wiki.
37383748 */
37393749 $wgFixDoubleRedirects = false;
37403750
@@ -3755,7 +3765,7 @@
37563766 * other namespaces cannot be invalidated by this variable.
37573767 */
37583768 $wgInvalidRedirectTargets = array( 'Filepath', 'Mypage', 'Mytalk' );
3759 -
 3769+
37603770 /**
37613771 * Array of namespaces to generate a sitemap for when the
37623772 * maintenance/generateSitemap.php script is run, or false if one is to be ge-
Index: trunk/phase3/includes/specials/SpecialListgrouprights.php
@@ -25,7 +25,7 @@
2626 */
2727 public function execute( $par ) {
2828 global $wgOut, $wgImplicitGroups, $wgMessageCache;
29 - global $wgGroupPermissions, $wgAddGroups, $wgRemoveGroups;
 29+ global $wgGroupPermissions, $wgRevokePermissions, $wgAddGroups, $wgRemoveGroups;
3030 global $wgGroupsAddToSelf, $wgGroupsRemoveFromSelf;
3131 $wgMessageCache->loadAllMessages();
3232
@@ -89,9 +89,9 @@
9090 $grouplink = '';
9191 }
9292
 93+ $revoke = isset( $wgRevokePermissions[$group] ) ? $wgRevokePermissions[$group] : array();
9394 $addgroups = isset( $wgAddGroups[$group] ) ? $wgAddGroups[$group] : array();
9495 $removegroups = isset( $wgRemoveGroups[$group] ) ? $wgRemoveGroups[$group] : array();
95 -
9696 $addgroupsSelf = isset( $wgGroupsAddToSelf[$group] ) ? $wgGroupsAddToSelf[$group] : array();
9797 $removegroupsSelf = isset( $wgGroupsRemoveFromSelf[$group] ) ? $wgGroupsRemoveFromSelf[$group] : array();
9898
@@ -101,27 +101,33 @@
102102 $grouppage . $grouplink .
103103 '</td>
104104 <td>' .
105 - self::formatPermissions( $permissions, $addgroups, $removegroups, $addgroupsSelf, $removegroupsSelf ) .
 105+ self::formatPermissions( $permissions, $revoke, $addgroups, $removegroups, $addgroupsSelf, $removegroupsSelf ) .
106106 '</td>
107107 </tr>'
108108 );
109109 }
110110 $wgOut->addHTML(
111 - Xml::closeElement( 'table' ) . "\n"
 111+ Xml::closeElement( 'table' ) . "\n<br /><hr />\n"
112112 );
 113+ $wgOut->addWikiMsg( 'listgrouprights-key' );
113114 }
114115
115116 /**
116117 * Create a user-readable list of permissions from the given array.
117118 *
118119 * @param $permissions Array of permission => bool (from $wgGroupPermissions items)
 120+ * @param $revoke Array of permission => bool (from $wgRevokePermissions items)
 121+ * @param $add Array of groups this group is allowed to add or true
 122+ * @param $remove Array of groups this group is allowed to remove or true
 123+ * @param $addSelf Array of groups this group is allowed to add to self or true
 124+ * @param $removeSelf Array of group this group is allowed to remove from self or true
119125 * @return string List of all granted permissions, separated by comma separator
120126 */
121 - private static function formatPermissions( $permissions, $add, $remove, $addSelf, $removeSelf ) {
 127+ private static function formatPermissions( $permissions, $revoke, $add, $remove, $addSelf, $removeSelf ) {
122128 global $wgLang;
123129 $r = array();
124130 foreach( $permissions as $permission => $granted ) {
125 - if ( $granted ) {
 131+ if( $granted ) {
126132 $description = wfMsgExt( 'listgrouprights-right-display', array( 'parseinline' ),
127133 User::getRightDescription( $permission ),
128134 $permission
@@ -129,6 +135,15 @@
130136 $r[] = $description;
131137 }
132138 }
 139+ foreach( $revoke as $permission => $revoked ) {
 140+ if( $revoked ) {
 141+ $description = wfMsgExt( 'lisgrouprights-right-revoked', array( 'parseinline' ),
 142+ User::getRightDescription( $permission ),
 143+ $permission
 144+ );
 145+ $r[] = $description;
 146+ }
 147+ }
133148 sort( $r );
134149 if( $add === true ){
135150 $r[] = wfMsgExt( 'listgrouprights-addgroup-all', array( 'escape' ) );
Index: trunk/phase3/includes/Autopromote.php
@@ -18,9 +18,9 @@
1919 if( self::recCheckCondition( $cond, $user ) )
2020 $promote[] = $group;
2121 }
22 -
 22+
2323 wfRunHooks( 'GetAutoPromoteGroups', array( $user, &$promote ) );
24 -
 24+
2525 return $promote;
2626 }
2727
@@ -116,6 +116,8 @@
117117 return $cond[1] == wfGetIP();
118118 case APCOND_IPINRANGE:
119119 return IP::isInRange( wfGetIP(), $cond[1] );
 120+ case APCOND_BLOCKED:
 121+ return $user->isBlocked();
120122 default:
121123 $result = null;
122124 wfRunHooks( 'AutopromoteCondition', array( $cond[0], array_slice( $cond, 1 ), $user, &$result ) );
Index: trunk/phase3/languages/messages/MessagesQqq.php
@@ -57,6 +57,7 @@
5858 * @author Platonides
5959 * @author Purodha
6060 * @author Raymond
 61+ * @author Ryan Schmidt
6162 * @author SPQRobin
6263 * @author Sanbec
6364 * @author Sborsody
@@ -298,7 +299,7 @@
299300 {{Identical|Error}}',
300301 'returnto' => '{{Identical|Return to $1}}',
301302 'tagline' => 'Used to idenify the source of copied information. Do not change <nowiki>{{SITENAME}}</nowiki>.',
302 -'help' => 'General text (noun) used in the sidebar (by default).
 303+'help' => 'General text (noun) used in the sidebar (by default).
303304
304305 See also [[MediaWiki:Helppage/{{SUBPAGENAME}}|{{int:helppage}}]] and [[MediaWiki:Edithelp/{{SUBPAGENAME}}|{{int:edithelp}}]].
305306
@@ -387,12 +388,12 @@
388389 'currentevents-url' => "Target page of ''{{Mediawiki:currentevents}}'' in the sidebar. See also {{msg|currentevents}}.
389390 {{doc-important|Do not translate <tt>Project:</tt> part.}}",
390391 'disclaimers' => 'Used as display name for the link to [[{{MediaWiki:Disclaimerpage}}]] shown at the bottom of every page on the wiki. Example [[{{MediaWiki:Disclaimerpage}}|{{MediaWiki:Disclaimers}}]].',
391 -'disclaimerpage' => 'Used as page for that contains the site disclaimer. Used at the bottom of every page on the wiki. Example: [[{{MediaWiki:Disclaimerpage}}|{{MediaWiki:Disclaimers}}]].
 392+'disclaimerpage' => 'Used as page for that contains the site disclaimer. Used at the bottom of every page on the wiki. Example: [[{{MediaWiki:Disclaimerpage}}|{{MediaWiki:Disclaimers}}]].
392393 {{doc-important|Do not change <tt>Project:</tt> part.}}',
393394 'edithelp' => 'This is the text that appears on the editing help link that is near the bottom of the editing page',
394 -'edithelppage' => 'The help page displayed when a user clicks on editing help link which is present on the right of Show changes button.
 395+'edithelppage' => 'The help page displayed when a user clicks on editing help link which is present on the right of Show changes button.
395396 {{doc-important|Do not change <tt>Help:</tt> part.}}',
396 -'helppage' => 'The link destination used by default in the sidebar, and in {{msg|noarticletext}}.
 397+'helppage' => 'The link destination used by default in the sidebar, and in {{msg|noarticletext}}.
397398 {{doc-important|Do not change <tt>Help:</tt> part.}}
398399 {{Identical|HelpContent}}',
399400 'mainpage' => 'Defines the link and display name of the main page of the wiki. Shown as the top link in the navigation part of the interface. Please do not change it too often, that could break things!
@@ -454,7 +455,7 @@
455456
456457 {{Identical|Hide}}',
457458 'restorelink' => "This text is always displayed in conjunction with the {{msg-mw|thisisdeleted}} message (View or restore $1?). The user will see
458 -View or restore <nowiki>{{PLURAL:$1|one deleted edit|$1 deleted edits}}</nowiki>? i.e ''View or restore one deleted edit?'' or
 459+View or restore <nowiki>{{PLURAL:$1|one deleted edit|$1 deleted edits}}</nowiki>? i.e ''View or restore one deleted edit?'' or
459460 ''View or restore n deleted edits?''",
460461 'feed-unavailable' => 'This message is displayed when a user tries to use an RSS or Atom feed on a wiki where such feeds have been disabled.',
461462 'site-rss-feed' => "Used in the HTML header of a wiki's RSS feed.
@@ -493,7 +494,7 @@
494495 # Main script and global functions
495496 'nosuchspecialpage' => 'The title of the error you get when trying to open a special page which does not exist. The text of the warning is the message {{msg-mw|nospecialpagetext}}. Example: [[Special:Nosuchpage]]',
496497 'nospecialpagetext' => 'This error is shown when trying to open a special page which does not exist, e.g. [[Special:Nosuchpage]].
497 -* The title of this error is the message {{msg-mw|nosuchspecialpage}}.
 498+* The title of this error is the message {{msg-mw|nosuchspecialpage}}.
498499 * Link <code><nowiki>[[Special:SpecialPages|{{int:specialpages}}]]</nowiki></code> should remain untranslated.',
499500
500501 # General errors
@@ -506,7 +507,7 @@
507508
508509 '''Parameters'''
509510 * $1: Pagename
510 -* $2: Content of
 511+* $2: Content of
511512 *# {{msg|Missingarticle-rev}} - Permalink with invalid revision#
512513 *# {{msg|Missingarticle-diff}} - Diff with invalid revision#",
513514 'missingarticle-rev' => 'Parameter $2 of {{msg|Missing-article}}: It is shown after the articlename.
@@ -692,7 +693,7 @@
693694 * <tt>$8</tt> is the timestamp when the block started',
694695 'blockednoreason' => '{{Identical|No reason given}}',
695696 'whitelistedittext' => '* $1 is a link to [[Special:UserLogin]] with {{msg-mw|loginreqlink}} as link description',
696 -'nosuchsectiontext' => 'This message is displayed when a user tries to edit a section that does not exist.
 697+'nosuchsectiontext' => 'This message is displayed when a user tries to edit a section that does not exist.
697698
698699 Parameter $1 is the content of section parameter in the URL (for example 1234 in the URL http://translatewiki.net/w/i.php?title=Sandbox&action=edit&section=1234)',
699700 'loginreqlink' => 'Take a look on inflection. Used as parameter in {{msg-mw|loginreqpagetext}}, {{msg-mw|whitelistedittext}}, {{msg-mw|watchlistanontext‎}} and {{msg-mw|Confirmemail needlogin}}.
@@ -860,7 +861,7 @@
861862 *Parameter $2 is the number of revisions for which the restrictions are changed.
862863
863864 Please note that the parameters in a log entry will appear in the log only in the default language of the wiki. View [[Special:Log]] for examples on translatewiki.net with English default language.',
864 -'logdelete-log-message' => 'This log message appears in brackets after the message {{msg|logdelete-logentry}} in the deletion or suppression logs when changing the visibility of a log entry for events. For a brief description of the process of changing the visibility of events and their log entries see this [http://www.mediawiki.org/wiki/RevisionDelete mediawiki explanation].
 865+'logdelete-log-message' => 'This log message appears in brackets after the message {{msg|logdelete-logentry}} in the deletion or suppression logs when changing the visibility of a log entry for events. For a brief description of the process of changing the visibility of events and their log entries see this [http://www.mediawiki.org/wiki/RevisionDelete mediawiki explanation].
865866
866867 *Parameter $1 is either {{msg|revdelete-hid}} (when hiding data), {{msg|revdelete-unhid}} (when unhiding data), {{msg|revdelete-restricted}} (when applying restrictions for sysops), {{msg|revdelete-unrestricted}} (when removing restrictions for sysops), or a combination of those messages.
867868 *Parameter $2 is the number of events for which the restrictions are changed.
@@ -985,7 +986,7 @@
986987 'searchall' => '{{Identical|All}}',
987988 'showingresults' => "This message is used on some special pages such as 'Wanted categories'. $1 is the total number of results in the batch shown and $2 is the number of the first item listed.",
988989 'showingresultsnum' => '$3 is the number of results on the page and $2 is the first number in the batch of results.',
989 -'showingresultstotal' => 'Text above list of search results on special page of search results.
 990+'showingresultstotal' => 'Text above list of search results on special page of search results.
990991 * $1–$2 is the range of results shown on the page
991992 * $3 is the total number of results from the search
992993 * $4 is the number of results shown on the page (equal to the size of the $1–$2 interval)',
@@ -1222,7 +1223,7 @@
12231224 * {{msg|right-suppressionlog|pl=yes}}
12241225 * {{msg|right-suppressrevision|pl=yes}}
12251226 * {{msg|right-deleterevision|pl=yes}}',
1226 -'right-ipblock-exempt' => 'This user automatically
 1227+'right-ipblock-exempt' => 'This user automatically
12271228 bypasses IP blocks, auto-blocks and range blocks - so I presume - but I am uncertain',
12281229 'right-rollback' => '{{Identical|Rollback}}',
12291230 'right-markbotedits' => '{{doc-right}}
@@ -1943,8 +1944,8 @@
19441945 <tt><nowiki>* Groupname</nowiki></tt> - defines a new group<br />
19451946 <tt><nowiki>** Reason</nowiki></tt> - defines a reason in this group',
19461947 'protect-edit-reasonlist' => 'Shown beneath the page protection form on the right side. It is a link to [[MediaWiki:Protect-dropdown]]. See also {{msg|Delete-edit-reasonlist}} and {{msg|Ipb-edit-dropdown}}.',
1947 -'protect-expiry-options' => "* Description: Options for the duration of the block.
1948 -* <font color=\"red\">Be careful:</font> '''1 translation:1 english''', so the first part is the translation and the second part should stay in English.
 1948+'protect-expiry-options' => "* Description: Options for the duration of the block.
 1949+* <font color=\"red\">Be careful:</font> '''1 translation:1 english''', so the first part is the translation and the second part should stay in English.
19491950 * Example: See e.g. [[MediaWiki:Protect-expiry-options/nl]] if you still don't know how to do it.
19501951
19511952 {{Identical|Infinite}}",
@@ -2087,8 +2088,8 @@
20882089 'ipbenableautoblock' => '{{Identical|Automatically block ...}}',
20892090 'ipbsubmit' => '{{Identical|Block this user}}',
20902091 'ipbother' => '{{Identical|Other time}}',
2091 -'ipboptions' => "* Description: Options for the duration of the block.
2092 -* <font color=\"red\">Be careful:</font> '''1 translation:1 english''', so the first part is the translation and the second part should stay in English.
 2092+'ipboptions' => "* Description: Options for the duration of the block.
 2093+* <font color=\"red\">Be careful:</font> '''1 translation:1 english''', so the first part is the translation and the second part should stay in English.
20932094 * Example: See e.g. [[MediaWiki:Ipboptions/nl]] if you still don't know how to do it.
20942095
20952096 {{Identical|Infinite}}",
@@ -2117,8 +2118,8 @@
21182119 * $1 - word "{{msg|Hide}}" or "{{msg|Show}}"',
21192120 'ipblocklist-submit' => '{{Identical|Search}}',
21202121 'blocklistline' => 'This is the text of an entry in the Special:IPBlockList.
2121 -* $1 is the hour and date of the block.
2122 -* $2 is the sysop.
 2122+* $1 is the hour and date of the block.
 2123+* $2 is the sysop.
21232124 * $3 is the blocked user or IP (with link to contributions and talk)
21242125 * $4 contains "hour and date of expiry, details (\'\'reason\'\')"
21252126
@@ -2137,7 +2138,7 @@
21382139
21392140 {{Identical|Block log}}',
21402141 'blocklog-fulllog' => 'Shown at Special:BlockIP at the end of the block log if there are more than 10 entries for this user, see [[Special:BlockIP/Raymond]] as example (visible for sysops only).',
2141 -'blocklogentry' => 'This is the text of an entry in the Block log (and RC), after hour (and date, only in the Block log) and sysop name:
 2142+'blocklogentry' => 'This is the text of an entry in the Block log (and RC), after hour (and date, only in the Block log) and sysop name:
21422143 * $1 is the blocked user or IP (with link to contributions and talk)
21432144 * $2 is the duration of the block (hours, days etc.) or the specified expiry date
21442145 * $3 contains "(details) (\'\'reason\'\')"
@@ -2355,7 +2356,7 @@
23562357 This message appears at the very end of the list of names in the message [[MediaWiki:Othercontribs/{{SUBPAGENAME}}|othercontribs]]. If there are no anonymous users in the credits list then this message does not appear at all.
23572358
23582359 * $1 is the number of anonymous users in the message',
2359 -'siteuser' => "This message is shown when viewing the credits of a page (example: {{fullurl:Main Page|action=credits}}). Note that this action is disabled by default (currently enabled on translatewiki.net).
 2360+'siteuser' => "This message is shown when viewing the credits of a page (example: {{fullurl:Main Page|action=credits}}). Note that this action is disabled by default (currently enabled on translatewiki.net).
23602361
23612362 This message is the variable $3 in the message {{msg-mw|lastmodifiedatby}}. This message only appears if the user has not entered his 'real name' in his preferences. The variable $1 in this message is a user name.
23622363
@@ -2369,7 +2370,7 @@
23702371 See also [[MediaWiki:Lastmodifiedat/{{SUBPAGENAME}}]].",
23712372 'othercontribs' => 'This message is shown when viewing the credits of a page (example: {{fullurl:Main Page|action=credits}}). Note that this action is disabled by default (currently enabled on translatewiki.net - to use type <nowiki>&action=credits</nowiki> at the end of any URL in the address bar).
23722373 * $1: the list of author(s) of the revisions preceding the current revision. It appears after the message [[Mediawiki:lastmodifiedatby/{{SUBPAGENAME}}]]. If there are no previous authors this message does not appear at all. If needed the messages [[Mediawiki:siteusers/{{SUBPAGENAME}}]], [[Mediawiki:anonymous/{{SUBPAGENAME}}]] and [[Mediawiki:and/{{SUBPAGENAME}}]] are part of the list of names.',
2373 -'others' => 'The following explanation is guesswork. This message is shown when viewing the credits of a page (example: {{fullurl:Main Page|action=credits}}). Note that this action is disabled by default (currently enabled on translatewiki.net - to use type <nowiki>&action=credits</nowiki> at the end of any URL in the address bar).
 2374+'others' => 'The following explanation is guesswork. This message is shown when viewing the credits of a page (example: {{fullurl:Main Page|action=credits}}). Note that this action is disabled by default (currently enabled on translatewiki.net - to use type <nowiki>&action=credits</nowiki> at the end of any URL in the address bar).
23742375
23752376 The message appears at the end of the list of credits given in the message [[Mediawiki:Othercontribs/{{SUBPAGENAME}}]] if the number of contributors is above a certain level.',
23762377 'siteusers' => 'This message is shown when viewing the credits of a page (example: {{fullurl:Main Page|action=credits}}). Note that this action is disabled by default (currently enabled on translatewiki.net).
@@ -2813,7 +2814,7 @@
28142815 *$3 is a URL to [[Special:ConfirmEmail]]
28152816 *$4 is a time and date (duplicated by $6 and $7)
28162817 *$5 is a URL to [[Special:InvalidateEmail]]
2817 -*$6 is a date
 2818+*$6 is a date
28182819 *$7 is a time',
28192820 'confirmemail_invalidated' => 'This is the text of the special page [[Special:InvalidateEmail|InvalidateEmail]] (with the title in [[Mediawiki:Invalidateemail]]) where user goes if he chooses the cancel e-mail confirmation link from the confirmation e-mail.',
28202821 'invalidateemail' => "This is the '''name of the special page''' where user goes if he chooses the cancel e-mail confirmation link from the confirmation e-mail.",
@@ -3009,14 +3010,14 @@
30103011
30113012 * $1: width of the file
30123013 * $2: height of the file
3013 -* $3: File size
 3014+* $3: File size
30143015 * $4: MIME type',
30153016 'fileduplicatesearch-result-1' => 'Result line after the list of files of [[Special:FileDuplicateSearch]]
30163017
30173018 $1 is the name of the requested file.',
30183019 'fileduplicatesearch-result-n' => 'Result line after the list of files of [[Special:FileDuplicateSearch]]
30193020
3020 -* $1 is the name of the requested file.
 3021+* $1 is the name of the requested file.
30213022 * $2 is the number of identical duplicates of the requested file',
30223023
30233024 # Special:SpecialPages
@@ -3077,4 +3078,7 @@
30783079
30793080 {{Identical|Other}}',
30803081
 3082+# Special:ListGroupRights
 3083+'listgrouprights-key' => 'Footer note for the [[Special:ListGroupRights]] page'
 3084+
30813085 );
Index: trunk/phase3/languages/messages/MessagesEn.php
@@ -2340,11 +2340,14 @@
23412341 'listgrouprights' => 'User group rights',
23422342 'listgrouprights-summary' => 'The following is a list of user groups defined on this wiki, with their associated access rights.
23432343 There may be [[{{MediaWiki:Listgrouprights-helppage}}|additional information]] about individual rights.',
 2344+'listgrouprights-key' => '* <span class="listgrouprights-granted">Granted right</span>
 2345+* <span class="listgrouprights-revoked">Revoked right</span>',
23442346 'listgrouprights-group' => 'Group',
23452347 'listgrouprights-rights' => 'Rights',
23462348 'listgrouprights-helppage' => 'Help:Group rights',
23472349 'listgrouprights-members' => '(list of members)',
2348 -'listgrouprights-right-display' => '$1 ($2)', # only translate this message to other languages if you have to change it
 2350+'listgrouprights-right-display' => '<span class="listgrouprights-granted">$1 ($2)</span>', # only translate this message to other languages if you have to change it
 2351+'listgrouprights-right-revoked' => '<span class="listgrouprights-revoked">$1 ($2)</span>', # only translate this message to other languages if you have to change it
23492352 'listgrouprights-addgroup' => 'Add {{PLURAL:$2|group|groups}}: $1',
23502353 'listgrouprights-removegroup' => 'Remove {{PLURAL:$2|group|groups}}: $1',
23512354 'listgrouprights-addgroup-all' => 'Add all groups',
@@ -3103,7 +3106,7 @@
31043107 'tooltip-recreate' => 'Recreate the page even though it has been deleted',
31053108 'tooltip-upload' => 'Start upload',
31063109 'tooltip-rollback' => '"Rollback" reverts edit(s) to this page of the last contributor in one click',
3107 -'tooltip-undo' => '"Undo" reverts this edit and opens the edit form in preview mode.
 3110+'tooltip-undo' => '"Undo" reverts this edit and opens the edit form in preview mode.
31083111 It allows adding a reason in the summary.',
31093112
31103113 # Stylesheets
Index: trunk/phase3/RELEASE-NOTES
@@ -87,6 +87,11 @@
8888 the arrangement of checkboxes on the Special:UserRights form
8989 * Add hook 'UserrightsSaveUserGroups' to give extensions the ability to modify
9090 the groups being added and removed last-minute.
 91+* Add autopromote condition APCOND_BLOCKED to autopromote blocked users to various
 92+ user groups.
 93+* Add $wgRemoveGroups as a means of restricting a group's rights. The syntax is
 94+ identical to $wgGroupPermissions, but users in these groups will have these rights
 95+ stripped from them.
9196
9297 === Bug fixes in 1.16 ===
9398

Follow-up revisions

RevisionCommit summaryAuthorDate
r52084* Fix typo in RELEASE-NOTES introduced in r52083: meant $wgRevokePermissions,...skizzerz03:38, 18 June 2009
r52118* Remove the two hooks introduced in r52082...skizzerz14:47, 18 June 2009
r52182Add missing message (r52083)siebrand22:32, 19 June 2009

Comments

#Comment by Tim Starling (talk | contribs)   06:41, 18 June 2009

Please configure your editor to preserve trailing spaces instead of stripping them off when you save the file. If you want to strip trailing spaces, you can do it in a separate commit to your feature additions.

#Comment by Tim Starling (talk | contribs)   06:58, 18 June 2009

There's an obvious bug in Special:ListGroupRights which suggests that you haven't tested this commit at all. Please test it and fix the bugs.

The interaction between $wgGroupPermissions and $wgRevokePermissions, when they conflict, seems to be undocumented, and the behaviour looks accidental. It depends on the order in which the groups are processed and this is not controllable in any obvious way. For instance if you have:

$wgGroupPermissions['bureaucrat']['upload'] = true;
$wgRevokePermissions['sysop']['upload'] = true;

Then if the groups are "sysop, bureaucrat", then the user will be able to upload, but if the groups are "bureaucrat, sysop", then the user will not be able to upload.

#Comment by Simetrical (talk | contribs)   19:54, 29 June 2009

You should add a couple of examples to the DefaultSettings docs.

#Comment by Tim Starling (talk | contribs)   07:32, 2 September 2009

Seems to be fixed by r52118.

Status & tagging log