Index: trunk/phase3/maintenance/language/messages.inc |
— | — | @@ -2070,10 +2070,12 @@ |
2071 | 2071 | 'ipbwatchuser', |
2072 | 2072 | 'ipb-disableusertalk', |
2073 | 2073 | 'ipb-change-block', |
| 2074 | + 'ipb-confirm', |
2074 | 2075 | 'badipaddress', |
2075 | 2076 | 'blockipsuccesssub', |
2076 | 2077 | 'blockipsuccesstext', |
2077 | 2078 | 'ipb-blockingself', |
| 2079 | + 'ipb-confirmhideuser', |
2078 | 2080 | 'ipb-edit-dropdown', |
2079 | 2081 | 'ipb-unblock-addr', |
2080 | 2082 | 'ipb-unblock', |
Index: trunk/phase3/includes/HTMLForm.php |
— | — | @@ -522,7 +522,7 @@ |
523 | 523 | * @param $errors Array of message keys/values |
524 | 524 | * @return String HTML, a <ul> list of errors |
525 | 525 | */ |
526 | | - static function formatErrors( $errors ) { |
| 526 | + public static function formatErrors( $errors ) { |
527 | 527 | $errorstr = ''; |
528 | 528 | |
529 | 529 | foreach ( $errors as $error ) { |
Index: trunk/phase3/includes/specials/SpecialBlock.php |
— | — | @@ -40,8 +40,17 @@ |
41 | 41 | /// @var Block::TYPE_ constant |
42 | 42 | protected $type; |
43 | 43 | |
| 44 | + /// @var User|String the previous block target |
| 45 | + protected $previousTarget; |
| 46 | + |
| 47 | + /// @var Bool whether the previous submission of the form asked for HideUser |
| 48 | + protected $requestedHideUser; |
| 49 | + |
44 | 50 | /// @var Bool |
45 | 51 | protected $alreadyBlocked; |
| 52 | + |
| 53 | + /// @var Array |
| 54 | + protected $preErrors = array(); |
46 | 55 | |
47 | 56 | public function __construct() { |
48 | 57 | parent::__construct( 'Block', 'block' ); |
— | — | @@ -71,6 +80,9 @@ |
72 | 81 | $wgUser->getSkin()->setRelevantUser( $this->target ); |
73 | 82 | } |
74 | 83 | |
| 84 | + list( $this->previousTarget, /*...*/ ) = Block::parseTarget( $wgRequest->getVal( 'wpPreviousTarget' ) ); |
| 85 | + $this->requestedHideUser = $wgRequest->getBool( 'wpHideUser' ); |
| 86 | + |
75 | 87 | # bug 15810: blocked admins should have limited access here |
76 | 88 | $status = self::checkUnblockSelf( $this->target ); |
77 | 89 | if ( $status !== true ) { |
— | — | @@ -81,7 +93,7 @@ |
82 | 94 | $wgOut->addModules( 'mediawiki.special', 'mediawiki.special.block' ); |
83 | 95 | |
84 | 96 | $fields = self::getFormFields(); |
85 | | - $this->alreadyBlocked = $this->maybeAlterFormDefaults( $fields ); |
| 97 | + $this->maybeAlterFormDefaults( $fields ); |
86 | 98 | |
87 | 99 | $form = new HTMLForm( $fields ); |
88 | 100 | $form->setTitle( $this->getTitle() ); |
— | — | @@ -94,6 +106,7 @@ |
95 | 107 | $form->setSubmitText( $t ); |
96 | 108 | |
97 | 109 | $this->doPreText( $form ); |
| 110 | + $this->doHeadertext( $form ); |
98 | 111 | $this->doPostText( $form ); |
99 | 112 | |
100 | 113 | if( $form->show() ){ |
— | — | @@ -183,11 +196,20 @@ |
184 | 197 | 'default' => false, |
185 | 198 | ); |
186 | 199 | |
187 | | - $a['AlreadyBlocked'] = array( |
| 200 | + # This is basically a copy of the Target field, but the user can't change it, so we |
| 201 | + # can see if the warnings we maybe showed to the user before still apply |
| 202 | + $a['PreviousTarget'] = array( |
188 | 203 | 'type' => 'hidden', |
189 | 204 | 'default' => false, |
190 | 205 | ); |
191 | 206 | |
| 207 | + # We'll turn this into a checkbox if we need to |
| 208 | + $a['Confirm'] = array( |
| 209 | + 'type' => 'hidden', |
| 210 | + 'default' => '', |
| 211 | + 'label-message' => 'ipb-confirm', |
| 212 | + ); |
| 213 | + |
192 | 214 | return $a; |
193 | 215 | } |
194 | 216 | |
— | — | @@ -199,8 +221,14 @@ |
200 | 222 | * already blocked) |
201 | 223 | */ |
202 | 224 | protected function maybeAlterFormDefaults( &$fields ){ |
| 225 | + global $wgRequest, $wgUser; |
| 226 | + |
| 227 | + # This will be overwritten by request data |
203 | 228 | $fields['Target']['default'] = (string)$this->target; |
204 | 229 | |
| 230 | + # This won't be |
| 231 | + $fields['PreviousTarget']['default'] = (string)$this->target; |
| 232 | + |
205 | 233 | $block = Block::newFromTarget( $this->target ); |
206 | 234 | |
207 | 235 | if( $block instanceof Block && !$block->mAuto # The block exists and isn't an autoblock |
— | — | @@ -221,17 +249,41 @@ |
222 | 250 | $fields['DisableUTEdit']['default'] = $block->prevents( 'editownusertalk' ); |
223 | 251 | } |
224 | 252 | $fields['Reason']['default'] = $block->mReason; |
225 | | - $fields['AlreadyBlocked']['default'] = htmlspecialchars( $block->getTarget() ); |
226 | 253 | |
| 254 | + if( $wgRequest->wasPosted() ){ |
| 255 | + # Ok, so we got a POST submission asking us to reblock a user. So show the |
| 256 | + # confirm checkbox; the user will only see it if they haven't previously |
| 257 | + $fields['Confirm']['type'] = 'check'; |
| 258 | + } else { |
| 259 | + # We got a target, but it wasn't a POST request, so the user must have gone |
| 260 | + # to a link like [[Special:Block/User]]. We don't need to show the checkbox |
| 261 | + # as long as they go ahead and block *that* user |
| 262 | + $fields['Confirm']['default'] = 1; |
| 263 | + } |
| 264 | + |
227 | 265 | if( $block->mExpiry == 'infinity' ) { |
228 | 266 | $fields['Expiry']['default'] = 'indefinite'; |
229 | 267 | } else { |
230 | 268 | $fields['Expiry']['default'] = wfTimestamp( TS_RFC2822, $block->mExpiry ); |
231 | 269 | } |
232 | 270 | |
233 | | - return true; |
| 271 | + $this->alreadyBlocked = true; |
| 272 | + $this->preErrors[] = array( 'ipb-needreblock', (string)$block->getTarget() ); |
234 | 273 | } |
235 | | - return false; |
| 274 | + |
| 275 | + # We always need confirmation to do HideUser |
| 276 | + if( $this->requestedHideUser ){ |
| 277 | + $fields['Confirm']['type'] = 'check'; |
| 278 | + unset( $fields['Confirm']['default'] ); |
| 279 | + $this->preErrors[] = 'ipb-confirmhideuser'; |
| 280 | + } |
| 281 | + |
| 282 | + # Or if the user is trying to block themselves |
| 283 | + if( (string)$this->target === $wgUser->getName() ){ |
| 284 | + $fields['Confirm']['type'] = 'check'; |
| 285 | + unset( $fields['Confirm']['default'] ); |
| 286 | + $this->preErrors[] = 'ipb-blockingself'; |
| 287 | + } |
236 | 288 | } |
237 | 289 | |
238 | 290 | /** |
— | — | @@ -265,17 +317,25 @@ |
266 | 318 | $form->addPreText( $s ); |
267 | 319 | } |
268 | 320 | } |
| 321 | + } |
269 | 322 | |
270 | | - # Username/IP is blocked already locally |
271 | | - if( $this->alreadyBlocked ) { |
272 | | - $form->addPreText( Html::rawElement( |
273 | | - 'div', |
274 | | - array( 'class' => 'mw-ipb-needreblock', ), |
275 | | - wfMsgExt( |
276 | | - 'ipb-needreblock', |
277 | | - array( 'parseinline' ), |
278 | | - $this->target |
279 | | - ) ) ); |
| 323 | + /** |
| 324 | + * Add header text inside the form, just underneath where the errors would go |
| 325 | + * @param $form HTMLForm |
| 326 | + * @return void |
| 327 | + */ |
| 328 | + protected function doHeaderText( HTMLForm &$form ){ |
| 329 | + global $wgRequest; |
| 330 | + # Don't need to do anything if the form has been posted |
| 331 | + if( !$wgRequest->wasPosted() && $this->preErrors ){ |
| 332 | + $s = HTMLForm::formatErrors( $this->preErrors ); |
| 333 | + if( $s ){ |
| 334 | + $form->addHeaderText( Html::rawElement( |
| 335 | + 'div', |
| 336 | + array( 'class' => 'error' ), |
| 337 | + $s |
| 338 | + ) ); |
| 339 | + } |
280 | 340 | } |
281 | 341 | } |
282 | 342 | |
— | — | @@ -481,6 +541,10 @@ |
482 | 542 | // Handled by field validator callback |
483 | 543 | // self::validateTargetField( $data['Target'] ); |
484 | 544 | |
| 545 | + # This might have been a hidden field or a checkbox, so interesting data |
| 546 | + # can come from it |
| 547 | + $data['Confirm'] = !in_array( $data['Confirm'], array( '', '0', null, false ), true ); |
| 548 | + |
485 | 549 | list( $target, $type ) = self::getTargetAndType( $data['Target'] ); |
486 | 550 | if( $type == Block::TYPE_USER ){ |
487 | 551 | $user = $target; |
— | — | @@ -490,8 +554,7 @@ |
491 | 555 | # Give admins a heads-up before they go and block themselves. Much messier |
492 | 556 | # to do this for IPs, but it's pretty unlikely they'd ever get the 'block' |
493 | 557 | # permission anyway, although the code does allow for it |
494 | | - if( $target === $wgUser->getName() |
495 | | - && $data['AlreadyBlocked'] != htmlspecialchars( $wgUser->getName() ) ) |
| 558 | + if( $target === $wgUser->getName() && ( $data['PreviousTarget'] != $data['Target'] || !$data['Confirm'] ) ) |
496 | 559 | { |
497 | 560 | return array( 'ipb-blockingself' ); |
498 | 561 | } |
— | — | @@ -544,6 +607,9 @@ |
545 | 608 | # Typically, the user should have a handful of edits. |
546 | 609 | # Disallow hiding users with many edits for performance. |
547 | 610 | return array( 'ipb_hide_invalid' ); |
| 611 | + |
| 612 | + } elseif( !$data['Confirm'] ){ |
| 613 | + return array( 'ipb-confirmhideuser' ); |
548 | 614 | } |
549 | 615 | } |
550 | 616 | |
— | — | @@ -568,7 +634,7 @@ |
569 | 635 | $status = $block->insert(); |
570 | 636 | if( !$status ) { |
571 | 637 | # Show form unless the user is already aware of this... |
572 | | - if( $data['AlreadyBlocked'] != htmlspecialchars( $block->getTarget() ) ) { |
| 638 | + if( ( $data['PreviousTarget'] != htmlspecialchars( $block->getTarget() ) ) || !$data['Confirm'] ) { |
573 | 639 | return array( array( 'ipb_already_blocked', $block->getTarget() ) ); |
574 | 640 | # Otherwise, try to update the block... |
575 | 641 | } else { |
Index: trunk/phase3/languages/messages/MessagesEn.php |
— | — | @@ -3056,11 +3056,13 @@ |
3057 | 3057 | 'ipbwatchuser' => "Watch this user's user and talk pages", |
3058 | 3058 | 'ipb-disableusertalk' => 'Prevent this user from editing their own talk page while blocked', |
3059 | 3059 | 'ipb-change-block' => 'Re-block the user with these settings', |
| 3060 | +'ipb-confirm' => 'Confirm block', |
3060 | 3061 | 'badipaddress' => 'Invalid IP address', |
3061 | 3062 | 'blockipsuccesssub' => 'Block succeeded', |
3062 | 3063 | 'blockipsuccesstext' => '[[Special:Contributions/$1|$1]] has been blocked.<br /> |
3063 | 3064 | See [[Special:IPBlockList|IP block list]] to review blocks.', |
3064 | 3065 | 'ipb-blockingself' => 'You are about to block yourself! Are you sure you want to do that?', |
| 3066 | +'ipb-confirmhideuser' => 'You are about to block a user with "hide user" enabled. This will suppress the user\'s name in all lists and log entries. Are you sure you want to do that?', |
3065 | 3067 | 'ipb-edit-dropdown' => 'Edit block reasons', |
3066 | 3068 | 'ipb-unblock-addr' => 'Unblock $1', |
3067 | 3069 | 'ipb-unblock' => 'Unblock a username or IP address', |
— | — | @@ -3126,13 +3128,10 @@ |
3127 | 3129 | 'ipb_expiry_temp' => 'Hidden username blocks must be permanent.', |
3128 | 3130 | 'ipb_hide_invalid' => 'Unable to suppress this account; it may have too many edits.', |
3129 | 3131 | 'ipb_already_blocked' => '"$1" is already blocked', |
3130 | | -'ipb-needreblock' => '== Already blocked == |
3131 | | -$1 is already blocked. |
3132 | | -Do you want to change the settings?', |
| 3132 | +'ipb-needreblock' => '$1 is already blocked. Do you want to change the settings?', |
3133 | 3133 | 'ipb-otherblocks-header' => 'Other {{PLURAL:$1|block|blocks}}', |
3134 | 3134 | 'unblock-hideuser' => 'You cannot unblock this user, as their username has been hidden.', |
3135 | | -'ipb_cant_unblock' => 'Error: Block ID $1 not found. |
3136 | | -It may have been unblocked already.', |
| 3135 | +'ipb_cant_unblock' => 'Error: Block ID $1 not found. It may have been unblocked already.', |
3137 | 3136 | 'ipb_blocked_as_range' => 'Error: The IP address $1 is not blocked directly and cannot be unblocked. |
3138 | 3137 | It is, however, blocked as part of the range $2, which can be unblocked.', |
3139 | 3138 | 'ip_range_invalid' => 'Invalid IP range.', |