r106511 MediaWiki - Code Review archive

Repository:MediaWiki
Revision:r106510‎ | r106511 | r106512 >
Date:18:11, 17 December 2011
Author:cervidae
Status:deferred (Comments)
Tags:
Comment:
Renaming SpecialBatchUserRights.php to BatchUserRights_body.php, adapting aliases file and changing a message in two languages
Modified paths:
  • /trunk/extensions/BatchUserRights/BatchUserRights.alias.php (modified) (history)
  • /trunk/extensions/BatchUserRights/BatchUserRights.i18n.php (modified) (history)
  • /trunk/extensions/BatchUserRights/BatchUserRights.php (modified) (history)
  • /trunk/extensions/BatchUserRights/BatchUserRights_body.php (added) (history)
  • /trunk/extensions/BatchUserRights/SpecialBatchUserRights.php (deleted) (history)

Diff [purge]

Index: trunk/extensions/BatchUserRights/SpecialBatchUserRights.php
@@ -1,553 +0,0 @@
2 -<?php
3 -/**
4 - * A class to manage user levels rights.
5 - *
6 - * @file
7 - * @ingroup SpecialPage
8 - */
9 -class SpecialBatchUserRights extends SpecialPage {
10 - protected $isself = false;
11 -
12 - /**
13 - * Constructor -- set up the new (restricted) special page
14 - */
15 - public function __construct() {
16 - parent::__construct( 'BatchUserRights', 'batchuserrights' );
17 - }
18 -
19 - public function userCanChangeRights( $user, $checkIfSelf = true ) {
20 - $available = $this->changeableGroups();
21 - return !empty( $available['add'] ) ||
22 - !empty( $available['remove'] ) ||
23 - ( ( $this->isself || !$checkIfSelf ) &&
24 - ( !empty( $available['add-self'] ) ||
25 - !empty( $available['remove-self'] ) ) );
26 - }
27 -
28 - /**
29 - * Manage forms to be shown according to posted data.
30 - * Depending on the submit button used, call a form or a save function.
31 - *
32 - * @param $par Mixed: string if any subpage provided, else null
33 - */
34 - public function execute( $par ) {
35 - global $wgUser, $wgRequest, $wgOut, $wgBatchUserRightsGrantableGroups;
36 -
37 - // If the visitor doesn't have permissions to assign or remove
38 - // any groups, it's a bit silly to give them the user search prompt.
39 - if ( !$wgUser->isAllowed( 'batchuserrights' ) ) {
40 - $this->displayRestrictionError();
41 - return;
42 - }
43 -
44 - // check if user is blocked -- see rt#19111
45 - if ( $wgUser->isBlocked() ) {
46 - $wgOut->blockedPage();
47 - return;
48 - }
49 -
50 - if ( wfReadOnly() ) {
51 - $wgOut->readOnlyPage();
52 - return;
53 - }
54 -
55 - $this->outputHeader();
56 -
57 - $this->setHeaders();
58 -
59 - if ( $wgRequest->wasPosted() ) {
60 - // Get the array of posted usernames (line-break delimited).
61 - $usernames = explode( "\n", $wgRequest->getVal( 'wpUsernames', '' ) );
62 -
63 - // save settings
64 - if ( $wgRequest->getCheck( 'saveusergroups' ) ) {
65 - $reason = $wgRequest->getVal( 'user-reason' );
66 - $tok = $wgRequest->getVal( 'wpEditToken' );
67 - if ( $wgUser->matchEditToken( $tok ) ) {
68 - $allgroups = $wgBatchUserRightsGrantableGroups;
69 - $addgroup = array();
70 - foreach ( $allgroups as $group ) {
71 - // This batch form is only for adding user groups, we don't remove any.
72 - if ( $wgRequest->getCheck( "wpGroup-$group" ) ) {
73 - $addgroup[] = $group;
74 - }
75 - }
76 -
77 - if ( count( $addgroup ) == 0 ) {
78 - $wgOut->addHTML(
79 - '<strong style="background-color:#faa">' .
80 - wfMsg( 'batchuserrights-no-groups' ) .
81 - "</strong><br /><br />\n"
82 - );
83 - } else {
84 - global $wgLang;
85 -
86 - $wgOut->addHTML( wfMsgExt(
87 - 'batchuserrights-add-groups',
88 - 'parseinline',
89 - count( $usernames ),
90 - count( $addgroup ),
91 - $wgLang->listToText( $addgroup )
92 - ) . "<br /><br />\n" );
93 - }
94 -
95 - // Loop through each target user and apply the update.
96 - foreach ( $usernames as $username ) {
97 - $username = trim( $username );
98 - if( $username !== '' ) {
99 - $wgOut->addHTML( wfMsgExt(
100 - 'batchuserrights-single-progress-update',
101 - 'parseinline',
102 - count( $addgroup ),
103 - $username
104 - ) . "<br />\n" );
105 - $this->saveUserGroups( $username, $addgroup, $reason );
106 - }
107 - }
108 - }
109 - }
110 - }
111 -
112 - // Show the list of avialable rights.
113 - $this->showEditUserGroupsForm();
114 - }
115 -
116 - /**
117 - * Save user groups changes in the database.
118 - * Data comes from the showEditUserGroupsForm() form function
119 - *
120 - * @param $username String: username to apply changes to.
121 - * @param $addgroup Array: group names which the user should be added to.
122 - * @param $reason String: reason for group change
123 - * @return null
124 - */
125 - function saveUserGroups( $username, $addgroup, $reason = '' ) {
126 - global $wgRequest, $wgUser;
127 -
128 - if ( $username == $wgUser->getName() ) {
129 - $this->isself = true;
130 - }
131 -
132 - $user = $this->fetchUser( $username );
133 - if ( !$user ) {
134 - global $wgOut;
135 -
136 - $wgOut->addHTML(
137 - '<strong style="background-color:#faa">' .
138 - wfMsgExt( 'batchuserrights-userload-error', 'parseinline', $username ) .
139 - '</strong><br />'
140 - );
141 -
142 - return;
143 - }
144 -
145 - // Validate input set...
146 - $changeable = $this->changeableGroups();
147 - $addable = array_merge( $changeable['add'], $this->isself ? $changeable['add-self'] : array() );
148 -
149 - $addgroup = array_unique(
150 - array_intersect( (array)$addgroup, $addable )
151 - );
152 -
153 - $oldGroups = $user->getGroups();
154 - $newGroups = $oldGroups;
155 -
156 - if ( $addgroup ) {
157 - $newGroups = array_merge( $newGroups, $addgroup );
158 - foreach ( $addgroup as $group ) {
159 - $user->addGroup( $group );
160 - }
161 - }
162 - $newGroups = array_unique( $newGroups );
163 -
164 - // Ensure that caches are cleared
165 - $user->invalidateCache();
166 -
167 - wfDebug( 'oldGroups: ' . print_r( $oldGroups, true ) );
168 - wfDebug( 'newGroups: ' . print_r( $newGroups, true ) );
169 - if ( $user instanceof User ) {
170 - $removegroup = array();
171 - // hmmm
172 - wfRunHooks( 'UserRights', array( &$user, $addgroup, $removegroup ) );
173 - }
174 -
175 - if ( $newGroups != $oldGroups ) {
176 - $this->addLogEntry( $user, $oldGroups, $newGroups );
177 - }
178 - }
179 -
180 - /**
181 - * Add a rights log entry for an action.
182 - */
183 - function addLogEntry( $user, $oldGroups, $newGroups ) {
184 - global $wgRequest;
185 - $log = new LogPage( 'rights' );
186 -
187 - $log->addEntry( 'rights',
188 - $user->getUserPage(),
189 - $wgRequest->getText( 'user-reason' ),
190 - array(
191 - $this->makeGroupNameListForLog( $oldGroups ),
192 - $this->makeGroupNameListForLog( $newGroups )
193 - )
194 - );
195 - }
196 -
197 - /**
198 - * Normalize the input username, which may be local or remote, and
199 - * return a user (or proxy) object for manipulating it.
200 - *
201 - * Side effects: error output for invalid access
202 - * @return mixed User, UserRightsProxy, or null
203 - */
204 - function fetchUser( $username ) {
205 - global $wgOut, $wgUser, $wgUserrightsInterwikiDelimiter;
206 -
207 - $parts = explode( $wgUserrightsInterwikiDelimiter, $username );
208 - if ( count( $parts ) < 2 ) {
209 - $name = trim( $username );
210 - $database = '';
211 - } else {
212 - list( $name, $database ) = array_map( 'trim', $parts );
213 -
214 - if ( !$wgUser->isAllowed( 'userrights-interwiki' ) ) {
215 - $wgOut->addWikiMsg( 'userrights-no-interwiki' );
216 - return null;
217 - }
218 - if ( !UserRightsProxy::validDatabase( $database ) ) {
219 - $wgOut->addWikiMsg( 'userrights-nodatabase', $database );
220 - return null;
221 - }
222 - }
223 -
224 - if ( $name == '' ) {
225 - $wgOut->addWikiMsg( 'nouserspecified' );
226 - return false;
227 - }
228 -
229 - if ( $name{0} == '#' ) {
230 - // Numeric ID can be specified...
231 - // We'll do a lookup for the name internally.
232 - $id = intval( substr( $name, 1 ) );
233 -
234 - if ( $database == '' ) {
235 - $name = User::whoIs( $id );
236 - } else {
237 - $name = UserRightsProxy::whoIs( $database, $id );
238 - }
239 -
240 - if ( !$name ) {
241 - $wgOut->addWikiMsg( 'noname' );
242 - return null;
243 - }
244 - }
245 -
246 - if ( $database == '' ) {
247 - $user = User::newFromName( $name );
248 - } else {
249 - $user = UserRightsProxy::newFromName( $database, $name );
250 - }
251 -
252 - if ( !$user || $user->isAnon() ) {
253 - $wgOut->addWikiMsg( 'nosuchusershort', $username );
254 - return null;
255 - }
256 -
257 - return $user;
258 - }
259 -
260 - function makeGroupNameList( $ids ) {
261 - if ( empty( $ids ) ) {
262 - return wfMsgForContent( 'rightsnone' );
263 - } else {
264 - return implode( ', ', $ids );
265 - }
266 - }
267 -
268 - function makeGroupNameListForLog( $ids ) {
269 - if ( empty( $ids ) ) {
270 - return '';
271 - } else {
272 - return $this->makeGroupNameList( $ids );
273 - }
274 - }
275 -
276 - /**
277 - * Go through used and available groups and return the ones that this
278 - * form will be able to manipulate based on the current user's system
279 - * permissions.
280 - *
281 - * @param $groups Array: list of groups the given user is in
282 - * @return Array: Tuple of addable, then removable groups
283 - */
284 - protected function splitGroups( $groups ) {
285 - list( $addable, $removable, $addself, $removeself ) = array_values( $this->changeableGroups() );
286 -
287 - $removable = array_intersect(
288 - array_merge( $this->isself ? $removeself : array(), $removable ),
289 - $groups
290 - ); // Can't remove groups the user doesn't have
291 - $addable = array_diff(
292 - array_merge( $this->isself ? $addself : array(), $addable ),
293 - $groups
294 - ); // Can't add groups the user does have
295 -
296 - return array( $addable, $removable );
297 - }
298 -
299 - /**
300 - * Show the form to add group memberships to one or more users at once.
301 - */
302 - protected function showEditUserGroupsForm() {
303 - global $wgOut, $wgUser;
304 -
305 - $wgOut->addHTML(
306 - Xml::openElement( 'form', array( 'method' => 'post', 'action' => $this->getTitle()->getLocalURL(), 'name' => 'editGroup', 'id' => 'mw-userrights-form2' ) ) .
307 - Html::hidden( 'wpEditToken', $wgUser->editToken() ) .
308 - Xml::openElement( 'fieldset' ) .
309 - Xml::element( 'legend', array(), wfMsg( 'userrights-editusergroup' ) ) .
310 - wfMsgExt( 'batchuserrights-intro', array( 'parse' ) ) .
311 - Xml::tags( 'p', null, $this->groupCheckboxes() ) .
312 - Xml::openElement( 'table', array( 'border' => '0', 'id' => 'mw-userrights-table-outer' ) ) .
313 - '<tr>
314 - <td class="mw-label">' .
315 - Xml::label( wfMsg( 'batchuserrights-names' ), 'wpUsernames' ) .
316 - '</td>
317 - <td class="mw-input">' .
318 - Xml::textarea( 'wpUsernames', '' ) .
319 - '</td>
320 - </tr>
321 - <tr>
322 - <td class="mw-label">' .
323 - Xml::label( wfMsg( 'userrights-reason' ), 'wpReason' ) .
324 - '</td>
325 - <td class="mw-input">' .
326 - Xml::input( 'user-reason', 60, false, array( 'id' => 'wpReason', 'maxlength' => 255 ) ) .
327 - '</td>
328 - </tr>
329 - <tr>
330 - <td></td>
331 - <td class="mw-submit">' .
332 - Xml::submitButton( wfMsg( 'saveusergroups' ), array( 'name' => 'saveusergroups', 'accesskey' => 's' ) ) .
333 - '</td>
334 - </tr>' .
335 - Xml::closeElement( 'table' ) . "\n" .
336 - Xml::closeElement( 'fieldset' ) .
337 - Xml::closeElement( 'form' ) . "\n"
338 - );
339 - }
340 -
341 - /**
342 - * Adds a table with checkboxes where you can select what groups to add/remove
343 - *
344 - * @return string XHTML table element with checkboxes
345 - */
346 - private function groupCheckboxes() {
347 - global $wgBatchUserRightsGrantableGroups;
348 - $usergroups = array(); // kinda a hack... this array holds "selected" groups... of which there shouldn't be any for this SpecialPage
349 -
350 - $allgroups = $wgBatchUserRightsGrantableGroups;
351 - $ret = '';
352 -
353 - $column = 1;
354 - $settable_col = '';
355 - $unsettable_col = '';
356 -
357 - foreach ( $allgroups as $group ) {
358 - $set = false;
359 - # Should the checkbox be disabled?
360 - $disabled = !( !$set && $this->canAdd( $group ) );
361 - # Do we need to point out that this action is irreversible?
362 - $irreversible = !$disabled && (
363 - ( $set && !$this->canAdd( $group ) ) ||
364 - ( !$set && !$this->canRemove( $group ) ) );
365 -
366 - /* Wikia change begin - @author: Marooned */
367 - /* Because of "return all" in changeableGroups() hook UserrightsChangeableGroups is not invoked - this hook is to fill this gap */
368 - wfRunHooks( 'UserRights::groupCheckboxes', array( $group, &$disabled, &$irreversible ) );
369 - /* Wikia change end */
370 -
371 - $attr = $disabled ? array( 'disabled' => 'disabled' ) : array();
372 - $attr['title'] = $group;
373 - $text = $irreversible
374 - ? wfMsgHtml( 'userrights-irreversible-marker', User::getGroupMember( $group ) )
375 - : User::getGroupMember( $group );
376 - $checkbox = Xml::checkLabel( $text, "wpGroup-$group",
377 - "wpGroup-$group", $set, $attr );
378 - $checkbox = $disabled ? Xml::tags( 'span', array( 'class' => 'mw-userrights-disabled' ), $checkbox ) : $checkbox;
379 -
380 - if ( $disabled ) {
381 - $unsettable_col .= "$checkbox<br />\n";
382 - } else {
383 - $settable_col .= "$checkbox<br />\n";
384 - }
385 - }
386 -
387 - if ( $column ) {
388 - $ret .= Xml::openElement( 'table', array( 'border' => '0', 'class' => 'mw-userrights-groups' ) ) .
389 - '<tr>
390 -';
391 - if ( $settable_col !== '' ) {
392 - $ret .= Xml::element( 'th', null, wfMsg( 'userrights-changeable-col' ) );
393 - }
394 - if ( $unsettable_col !== '' ) {
395 - $ret .= Xml::element( 'th', null, wfMsg( 'userrights-unchangeable-col' ) );
396 - }
397 - $ret .= '</tr>
398 - <tr>
399 -';
400 - if ( $settable_col !== '' ) {
401 - $ret .=
402 -" <td style='vertical-align:top;'>
403 - $settable_col
404 - </td>
405 -";
406 - }
407 - if ( $unsettable_col !== '' ) {
408 - $ret .=
409 -" <td style='vertical-align:top;'>
410 - $unsettable_col
411 - </td>
412 -";
413 - }
414 - $ret .= Xml::closeElement( 'tr' ) . Xml::closeElement( 'table' );
415 - }
416 -
417 - return $ret;
418 - }
419 -
420 - /**
421 - * @param $group String: the name of the group to check
422 - * @return bool Can we remove the group?
423 - */
424 - private function canRemove( $group ) {
425 - // $this->changeableGroups()['remove'] doesn't work, of course. Thanks,
426 - // PHP.
427 - $groups = $this->changeableGroups();
428 - return in_array( $group, $groups['remove'] ) || ( $this->isself && in_array( $group, $groups['remove-self'] ) );
429 - }
430 -
431 - /**
432 - * @param $group string: the name of the group to check
433 - * @return bool Can we add the group?
434 - */
435 - private function canAdd( $group ) {
436 - $groups = $this->changeableGroups();
437 - return in_array( $group, $groups['add'] ) || ( $this->isself && in_array( $group, $groups['add-self'] ) );
438 - }
439 -
440 - /**
441 - * Returns an array of the groups that the user can add/remove.
442 - *
443 - * @return Array array( 'add' => array( addablegroups ), 'remove' => array( removablegroups ) , 'add-self' => array( addablegroups to self), 'remove-self' => array( removable groups from self) )
444 - */
445 - function changeableGroups() {
446 - global $wgUser;
447 -
448 - if ( $wgUser->isAllowed( 'userrights' ) ) {
449 - // This group gives the right to modify everything (reverse-
450 - // compatibility with old "userrights lets you change
451 - // everything")
452 - // Using array_merge to make the groups reindexed
453 - $all = array_merge( User::getAllGroups() );
454 - return array(
455 - 'add' => $all,
456 - 'remove' => $all,
457 - 'add-self' => array(),
458 - 'remove-self' => array()
459 - );
460 - }
461 -
462 - // Okay, it's not so simple, we will have to go through the arrays
463 - $groups = array(
464 - 'add' => array(),
465 - 'remove' => array(),
466 - 'add-self' => array(),
467 - 'remove-self' => array()
468 - );
469 - $addergroups = $wgUser->getEffectiveGroups();
470 -
471 - foreach ( $addergroups as $addergroup ) {
472 - $groups = array_merge_recursive(
473 - $groups, $this->changeableByGroup( $addergroup )
474 - );
475 - $groups['add'] = array_unique( $groups['add'] );
476 - $groups['remove'] = array_unique( $groups['remove'] );
477 - $groups['add-self'] = array_unique( $groups['add-self'] );
478 - $groups['remove-self'] = array_unique( $groups['remove-self'] );
479 - }
480 -
481 - // Run a hook because we can
482 - wfRunHooks( 'UserrightsChangeableGroups', array( $this, $wgUser, $addergroups, &$groups ) );
483 -
484 - return $groups;
485 - }
486 -
487 - /**
488 - * Returns an array of the groups that a particular group can add/remove.
489 - *
490 - * @param $group String: the group to check for whether it can add/remove
491 - * @return Array array( 'add' => array( addablegroups ), 'remove' => array( removablegroups ) , 'add-self' => array( addablegroups to self), 'remove-self' => array( removable groups from self) )
492 - */
493 - private function changeableByGroup( $group ) {
494 - global $wgAddGroups, $wgRemoveGroups, $wgGroupsAddToSelf, $wgGroupsRemoveFromSelf;
495 -
496 - $groups = array(
497 - 'add' => array(),
498 - 'remove' => array(),
499 - 'add-self' => array(),
500 - 'remove-self' => array()
501 - );
502 - if ( empty( $wgAddGroups[$group] ) ) {
503 - // Don't add anything to $groups
504 - } elseif ( $wgAddGroups[$group] === true ) {
505 - // You get everything
506 - $groups['add'] = User::getAllGroups();
507 - } elseif ( is_array( $wgAddGroups[$group] ) ) {
508 - $groups['add'] = $wgAddGroups[$group];
509 - }
510 -
511 - // Same thing for remove
512 - if ( empty( $wgRemoveGroups[$group] ) ) {
513 - } elseif ( $wgRemoveGroups[$group] === true ) {
514 - $groups['remove'] = User::getAllGroups();
515 - } elseif ( is_array( $wgRemoveGroups[$group] ) ) {
516 - $groups['remove'] = $wgRemoveGroups[$group];
517 - }
518 -
519 - // Re-map numeric keys of AddToSelf/RemoveFromSelf to the 'user' key for backwards compatibility
520 - if ( empty( $wgGroupsAddToSelf['user'] ) || $wgGroupsAddToSelf['user'] !== true ) {
521 - foreach ( $wgGroupsAddToSelf as $key => $value ) {
522 - if ( is_int( $key ) ) {
523 - $wgGroupsAddToSelf['user'][] = $value;
524 - }
525 - }
526 - }
527 -
528 - if ( empty( $wgGroupsRemoveFromSelf['user'] ) || $wgGroupsRemoveFromSelf['user'] !== true ) {
529 - foreach ( $wgGroupsRemoveFromSelf as $key => $value ) {
530 - if ( is_int( $key ) ) {
531 - $wgGroupsRemoveFromSelf['user'][] = $value;
532 - }
533 - }
534 - }
535 -
536 - // Now figure out what groups the user can add to him/herself
537 - if ( empty( $wgGroupsAddToSelf[$group] ) ) {
538 - } elseif ( $wgGroupsAddToSelf[$group] === true ) {
539 - // No idea WHY this would be used, but it's there
540 - $groups['add-self'] = User::getAllGroups();
541 - } elseif ( is_array( $wgGroupsAddToSelf[$group] ) ) {
542 - $groups['add-self'] = $wgGroupsAddToSelf[$group];
543 - }
544 -
545 - if ( empty( $wgGroupsRemoveFromSelf[$group] ) ) {
546 - } elseif ( $wgGroupsRemoveFromSelf[$group] === true ) {
547 - $groups['remove-self'] = User::getAllGroups();
548 - } elseif ( is_array( $wgGroupsRemoveFromSelf[$group] ) ) {
549 - $groups['remove-self'] = $wgGroupsRemoveFromSelf[$group];
550 - }
551 -
552 - return $groups;
553 - }
554 -}
Index: trunk/extensions/BatchUserRights/BatchUserRights.alias.php
@@ -1,15 +1,27 @@
22 <?php
33 /**
4 - * Aliases for Special:BatchUserRights.
 4+ * Aliases for Special:BatchUserRights
55 *
66 * @file
77 */
88
9 -$aliases = array();
 9+$specialPageAliases = array();
1010
1111 /** English
1212 * @author Sean Colombo
1313 */
14 -$aliases['en'] = array(
 14+$specialPageAliases['en'] = array(
1515 'BatchUserRights' => array( 'BatchUserRights' ),
16 -);
\ No newline at end of file
 16+);
 17+
 18+/** German (Deutsch)
 19+ * @author SVG
 20+ */
 21+$specialPageAliases['de'] = array(
 22+ 'BatchUserRights' => array( 'Massen-Benutzerrechte' ),
 23+);
 24+
 25+/**
 26+ * For backwards compatibility with MediaWiki 1.15 and earlier.
 27+ */
 28+$aliases =& $specialPageAliases;
Index: trunk/extensions/BatchUserRights/BatchUserRights_body.php
@@ -0,0 +1,553 @@
 2+<?php
 3+/**
 4+ * A class to manage user levels rights.
 5+ *
 6+ * @file
 7+ * @ingroup SpecialPage
 8+ */
 9+class SpecialBatchUserRights extends SpecialPage {
 10+ protected $isself = false;
 11+
 12+ /**
 13+ * Constructor -- set up the new (restricted) special page
 14+ */
 15+ public function __construct() {
 16+ parent::__construct( 'BatchUserRights', 'batchuserrights' );
 17+ }
 18+
 19+ public function userCanChangeRights( $user, $checkIfSelf = true ) {
 20+ $available = $this->changeableGroups();
 21+ return !empty( $available['add'] ) ||
 22+ !empty( $available['remove'] ) ||
 23+ ( ( $this->isself || !$checkIfSelf ) &&
 24+ ( !empty( $available['add-self'] ) ||
 25+ !empty( $available['remove-self'] ) ) );
 26+ }
 27+
 28+ /**
 29+ * Manage forms to be shown according to posted data.
 30+ * Depending on the submit button used, call a form or a save function.
 31+ *
 32+ * @param $par Mixed: string if any subpage provided, else null
 33+ */
 34+ public function execute( $par ) {
 35+ global $wgUser, $wgRequest, $wgOut, $wgBatchUserRightsGrantableGroups;
 36+
 37+ // If the visitor doesn't have permissions to assign or remove
 38+ // any groups, it's a bit silly to give them the user search prompt.
 39+ if ( !$wgUser->isAllowed( 'batchuserrights' ) ) {
 40+ $this->displayRestrictionError();
 41+ return;
 42+ }
 43+
 44+ // check if user is blocked -- see rt#19111
 45+ if ( $wgUser->isBlocked() ) {
 46+ $wgOut->blockedPage();
 47+ return;
 48+ }
 49+
 50+ if ( wfReadOnly() ) {
 51+ $wgOut->readOnlyPage();
 52+ return;
 53+ }
 54+
 55+ $this->outputHeader();
 56+
 57+ $this->setHeaders();
 58+
 59+ if ( $wgRequest->wasPosted() ) {
 60+ // Get the array of posted usernames (line-break delimited).
 61+ $usernames = explode( "\n", $wgRequest->getVal( 'wpUsernames', '' ) );
 62+
 63+ // save settings
 64+ if ( $wgRequest->getCheck( 'saveusergroups' ) ) {
 65+ $reason = $wgRequest->getVal( 'user-reason' );
 66+ $tok = $wgRequest->getVal( 'wpEditToken' );
 67+ if ( $wgUser->matchEditToken( $tok ) ) {
 68+ $allgroups = $wgBatchUserRightsGrantableGroups;
 69+ $addgroup = array();
 70+ foreach ( $allgroups as $group ) {
 71+ // This batch form is only for adding user groups, we don't remove any.
 72+ if ( $wgRequest->getCheck( "wpGroup-$group" ) ) {
 73+ $addgroup[] = $group;
 74+ }
 75+ }
 76+
 77+ if ( count( $addgroup ) == 0 ) {
 78+ $wgOut->addHTML(
 79+ '<strong style="background-color:#faa">' .
 80+ wfMsg( 'batchuserrights-no-groups' ) .
 81+ "</strong><br /><br />\n"
 82+ );
 83+ } else {
 84+ global $wgLang;
 85+
 86+ $wgOut->addHTML( wfMsgExt(
 87+ 'batchuserrights-add-groups',
 88+ 'parseinline',
 89+ count( $usernames ),
 90+ count( $addgroup ),
 91+ $wgLang->listToText( $addgroup )
 92+ ) . "<br /><br />\n" );
 93+ }
 94+
 95+ // Loop through each target user and apply the update.
 96+ foreach ( $usernames as $username ) {
 97+ $username = trim( $username );
 98+ if( $username !== '' ) {
 99+ $wgOut->addHTML( wfMsgExt(
 100+ 'batchuserrights-single-progress-update',
 101+ 'parseinline',
 102+ count( $addgroup ),
 103+ $username
 104+ ) . "<br />\n" );
 105+ $this->saveUserGroups( $username, $addgroup, $reason );
 106+ }
 107+ }
 108+ }
 109+ }
 110+ }
 111+
 112+ // Show the list of avialable rights.
 113+ $this->showEditUserGroupsForm();
 114+ }
 115+
 116+ /**
 117+ * Save user groups changes in the database.
 118+ * Data comes from the showEditUserGroupsForm() form function
 119+ *
 120+ * @param $username String: username to apply changes to.
 121+ * @param $addgroup Array: group names which the user should be added to.
 122+ * @param $reason String: reason for group change
 123+ * @return null
 124+ */
 125+ function saveUserGroups( $username, $addgroup, $reason = '' ) {
 126+ global $wgRequest, $wgUser;
 127+
 128+ if ( $username == $wgUser->getName() ) {
 129+ $this->isself = true;
 130+ }
 131+
 132+ $user = $this->fetchUser( $username );
 133+ if ( !$user ) {
 134+ global $wgOut;
 135+
 136+ $wgOut->addHTML(
 137+ '<strong style="background-color:#faa">' .
 138+ wfMsgExt( 'batchuserrights-userload-error', 'parseinline', $username ) .
 139+ '</strong><br />'
 140+ );
 141+
 142+ return;
 143+ }
 144+
 145+ // Validate input set...
 146+ $changeable = $this->changeableGroups();
 147+ $addable = array_merge( $changeable['add'], $this->isself ? $changeable['add-self'] : array() );
 148+
 149+ $addgroup = array_unique(
 150+ array_intersect( (array)$addgroup, $addable )
 151+ );
 152+
 153+ $oldGroups = $user->getGroups();
 154+ $newGroups = $oldGroups;
 155+
 156+ if ( $addgroup ) {
 157+ $newGroups = array_merge( $newGroups, $addgroup );
 158+ foreach ( $addgroup as $group ) {
 159+ $user->addGroup( $group );
 160+ }
 161+ }
 162+ $newGroups = array_unique( $newGroups );
 163+
 164+ // Ensure that caches are cleared
 165+ $user->invalidateCache();
 166+
 167+ wfDebug( 'oldGroups: ' . print_r( $oldGroups, true ) );
 168+ wfDebug( 'newGroups: ' . print_r( $newGroups, true ) );
 169+ if ( $user instanceof User ) {
 170+ $removegroup = array();
 171+ // hmmm
 172+ wfRunHooks( 'UserRights', array( &$user, $addgroup, $removegroup ) );
 173+ }
 174+
 175+ if ( $newGroups != $oldGroups ) {
 176+ $this->addLogEntry( $user, $oldGroups, $newGroups );
 177+ }
 178+ }
 179+
 180+ /**
 181+ * Add a rights log entry for an action.
 182+ */
 183+ function addLogEntry( $user, $oldGroups, $newGroups ) {
 184+ global $wgRequest;
 185+ $log = new LogPage( 'rights' );
 186+
 187+ $log->addEntry( 'rights',
 188+ $user->getUserPage(),
 189+ $wgRequest->getText( 'user-reason' ),
 190+ array(
 191+ $this->makeGroupNameListForLog( $oldGroups ),
 192+ $this->makeGroupNameListForLog( $newGroups )
 193+ )
 194+ );
 195+ }
 196+
 197+ /**
 198+ * Normalize the input username, which may be local or remote, and
 199+ * return a user (or proxy) object for manipulating it.
 200+ *
 201+ * Side effects: error output for invalid access
 202+ * @return mixed User, UserRightsProxy, or null
 203+ */
 204+ function fetchUser( $username ) {
 205+ global $wgOut, $wgUser, $wgUserrightsInterwikiDelimiter;
 206+
 207+ $parts = explode( $wgUserrightsInterwikiDelimiter, $username );
 208+ if ( count( $parts ) < 2 ) {
 209+ $name = trim( $username );
 210+ $database = '';
 211+ } else {
 212+ list( $name, $database ) = array_map( 'trim', $parts );
 213+
 214+ if ( !$wgUser->isAllowed( 'userrights-interwiki' ) ) {
 215+ $wgOut->addWikiMsg( 'userrights-no-interwiki' );
 216+ return null;
 217+ }
 218+ if ( !UserRightsProxy::validDatabase( $database ) ) {
 219+ $wgOut->addWikiMsg( 'userrights-nodatabase', $database );
 220+ return null;
 221+ }
 222+ }
 223+
 224+ if ( $name == '' ) {
 225+ $wgOut->addWikiMsg( 'nouserspecified' );
 226+ return false;
 227+ }
 228+
 229+ if ( $name{0} == '#' ) {
 230+ // Numeric ID can be specified...
 231+ // We'll do a lookup for the name internally.
 232+ $id = intval( substr( $name, 1 ) );
 233+
 234+ if ( $database == '' ) {
 235+ $name = User::whoIs( $id );
 236+ } else {
 237+ $name = UserRightsProxy::whoIs( $database, $id );
 238+ }
 239+
 240+ if ( !$name ) {
 241+ $wgOut->addWikiMsg( 'noname' );
 242+ return null;
 243+ }
 244+ }
 245+
 246+ if ( $database == '' ) {
 247+ $user = User::newFromName( $name );
 248+ } else {
 249+ $user = UserRightsProxy::newFromName( $database, $name );
 250+ }
 251+
 252+ if ( !$user || $user->isAnon() ) {
 253+ $wgOut->addWikiMsg( 'nosuchusershort', $username );
 254+ return null;
 255+ }
 256+
 257+ return $user;
 258+ }
 259+
 260+ function makeGroupNameList( $ids ) {
 261+ if ( empty( $ids ) ) {
 262+ return wfMsgForContent( 'rightsnone' );
 263+ } else {
 264+ return implode( ', ', $ids );
 265+ }
 266+ }
 267+
 268+ function makeGroupNameListForLog( $ids ) {
 269+ if ( empty( $ids ) ) {
 270+ return '';
 271+ } else {
 272+ return $this->makeGroupNameList( $ids );
 273+ }
 274+ }
 275+
 276+ /**
 277+ * Go through used and available groups and return the ones that this
 278+ * form will be able to manipulate based on the current user's system
 279+ * permissions.
 280+ *
 281+ * @param $groups Array: list of groups the given user is in
 282+ * @return Array: Tuple of addable, then removable groups
 283+ */
 284+ protected function splitGroups( $groups ) {
 285+ list( $addable, $removable, $addself, $removeself ) = array_values( $this->changeableGroups() );
 286+
 287+ $removable = array_intersect(
 288+ array_merge( $this->isself ? $removeself : array(), $removable ),
 289+ $groups
 290+ ); // Can't remove groups the user doesn't have
 291+ $addable = array_diff(
 292+ array_merge( $this->isself ? $addself : array(), $addable ),
 293+ $groups
 294+ ); // Can't add groups the user does have
 295+
 296+ return array( $addable, $removable );
 297+ }
 298+
 299+ /**
 300+ * Show the form to add group memberships to one or more users at once.
 301+ */
 302+ protected function showEditUserGroupsForm() {
 303+ global $wgOut, $wgUser;
 304+
 305+ $wgOut->addHTML(
 306+ Xml::openElement( 'form', array( 'method' => 'post', 'action' => $this->getTitle()->getLocalURL(), 'name' => 'editGroup', 'id' => 'mw-userrights-form2' ) ) .
 307+ Html::hidden( 'wpEditToken', $wgUser->editToken() ) .
 308+ Xml::openElement( 'fieldset' ) .
 309+ Xml::element( 'legend', array(), wfMsg( 'userrights-editusergroup' ) ) .
 310+ wfMsgExt( 'batchuserrights-intro', array( 'parse' ) ) .
 311+ Xml::tags( 'p', null, $this->groupCheckboxes() ) .
 312+ Xml::openElement( 'table', array( 'border' => '0', 'id' => 'mw-userrights-table-outer' ) ) .
 313+ '<tr>
 314+ <td class="mw-label">' .
 315+ Xml::label( wfMsg( 'batchuserrights-names' ), 'wpUsernames' ) .
 316+ '</td>
 317+ <td class="mw-input">' .
 318+ Xml::textarea( 'wpUsernames', '' ) .
 319+ '</td>
 320+ </tr>
 321+ <tr>
 322+ <td class="mw-label">' .
 323+ Xml::label( wfMsg( 'userrights-reason' ), 'wpReason' ) .
 324+ '</td>
 325+ <td class="mw-input">' .
 326+ Xml::input( 'user-reason', 60, false, array( 'id' => 'wpReason', 'maxlength' => 255 ) ) .
 327+ '</td>
 328+ </tr>
 329+ <tr>
 330+ <td></td>
 331+ <td class="mw-submit">' .
 332+ Xml::submitButton( wfMsg( 'saveusergroups' ), array( 'name' => 'saveusergroups', 'accesskey' => 's' ) ) .
 333+ '</td>
 334+ </tr>' .
 335+ Xml::closeElement( 'table' ) . "\n" .
 336+ Xml::closeElement( 'fieldset' ) .
 337+ Xml::closeElement( 'form' ) . "\n"
 338+ );
 339+ }
 340+
 341+ /**
 342+ * Adds a table with checkboxes where you can select what groups to add/remove
 343+ *
 344+ * @return string XHTML table element with checkboxes
 345+ */
 346+ private function groupCheckboxes() {
 347+ global $wgBatchUserRightsGrantableGroups;
 348+ $usergroups = array(); // kinda a hack... this array holds "selected" groups... of which there shouldn't be any for this SpecialPage
 349+
 350+ $allgroups = $wgBatchUserRightsGrantableGroups;
 351+ $ret = '';
 352+
 353+ $column = 1;
 354+ $settable_col = '';
 355+ $unsettable_col = '';
 356+
 357+ foreach ( $allgroups as $group ) {
 358+ $set = false;
 359+ # Should the checkbox be disabled?
 360+ $disabled = !( !$set && $this->canAdd( $group ) );
 361+ # Do we need to point out that this action is irreversible?
 362+ $irreversible = !$disabled && (
 363+ ( $set && !$this->canAdd( $group ) ) ||
 364+ ( !$set && !$this->canRemove( $group ) ) );
 365+
 366+ /* Wikia change begin - @author: Marooned */
 367+ /* Because of "return all" in changeableGroups() hook UserrightsChangeableGroups is not invoked - this hook is to fill this gap */
 368+ wfRunHooks( 'UserRights::groupCheckboxes', array( $group, &$disabled, &$irreversible ) );
 369+ /* Wikia change end */
 370+
 371+ $attr = $disabled ? array( 'disabled' => 'disabled' ) : array();
 372+ $attr['title'] = $group;
 373+ $text = $irreversible
 374+ ? wfMsgHtml( 'userrights-irreversible-marker', User::getGroupMember( $group ) )
 375+ : User::getGroupMember( $group );
 376+ $checkbox = Xml::checkLabel( $text, "wpGroup-$group",
 377+ "wpGroup-$group", $set, $attr );
 378+ $checkbox = $disabled ? Xml::tags( 'span', array( 'class' => 'mw-userrights-disabled' ), $checkbox ) : $checkbox;
 379+
 380+ if ( $disabled ) {
 381+ $unsettable_col .= "$checkbox<br />\n";
 382+ } else {
 383+ $settable_col .= "$checkbox<br />\n";
 384+ }
 385+ }
 386+
 387+ if ( $column ) {
 388+ $ret .= Xml::openElement( 'table', array( 'border' => '0', 'class' => 'mw-userrights-groups' ) ) .
 389+ '<tr>
 390+';
 391+ if ( $settable_col !== '' ) {
 392+ $ret .= Xml::element( 'th', null, wfMsg( 'userrights-changeable-col' ) );
 393+ }
 394+ if ( $unsettable_col !== '' ) {
 395+ $ret .= Xml::element( 'th', null, wfMsg( 'userrights-unchangeable-col' ) );
 396+ }
 397+ $ret .= '</tr>
 398+ <tr>
 399+';
 400+ if ( $settable_col !== '' ) {
 401+ $ret .=
 402+" <td style='vertical-align:top;'>
 403+ $settable_col
 404+ </td>
 405+";
 406+ }
 407+ if ( $unsettable_col !== '' ) {
 408+ $ret .=
 409+" <td style='vertical-align:top;'>
 410+ $unsettable_col
 411+ </td>
 412+";
 413+ }
 414+ $ret .= Xml::closeElement( 'tr' ) . Xml::closeElement( 'table' );
 415+ }
 416+
 417+ return $ret;
 418+ }
 419+
 420+ /**
 421+ * @param $group String: the name of the group to check
 422+ * @return bool Can we remove the group?
 423+ */
 424+ private function canRemove( $group ) {
 425+ // $this->changeableGroups()['remove'] doesn't work, of course. Thanks,
 426+ // PHP.
 427+ $groups = $this->changeableGroups();
 428+ return in_array( $group, $groups['remove'] ) || ( $this->isself && in_array( $group, $groups['remove-self'] ) );
 429+ }
 430+
 431+ /**
 432+ * @param $group string: the name of the group to check
 433+ * @return bool Can we add the group?
 434+ */
 435+ private function canAdd( $group ) {
 436+ $groups = $this->changeableGroups();
 437+ return in_array( $group, $groups['add'] ) || ( $this->isself && in_array( $group, $groups['add-self'] ) );
 438+ }
 439+
 440+ /**
 441+ * Returns an array of the groups that the user can add/remove.
 442+ *
 443+ * @return Array array( 'add' => array( addablegroups ), 'remove' => array( removablegroups ) , 'add-self' => array( addablegroups to self), 'remove-self' => array( removable groups from self) )
 444+ */
 445+ function changeableGroups() {
 446+ global $wgUser;
 447+
 448+ if ( $wgUser->isAllowed( 'userrights' ) ) {
 449+ // This group gives the right to modify everything (reverse-
 450+ // compatibility with old "userrights lets you change
 451+ // everything")
 452+ // Using array_merge to make the groups reindexed
 453+ $all = array_merge( User::getAllGroups() );
 454+ return array(
 455+ 'add' => $all,
 456+ 'remove' => $all,
 457+ 'add-self' => array(),
 458+ 'remove-self' => array()
 459+ );
 460+ }
 461+
 462+ // Okay, it's not so simple, we will have to go through the arrays
 463+ $groups = array(
 464+ 'add' => array(),
 465+ 'remove' => array(),
 466+ 'add-self' => array(),
 467+ 'remove-self' => array()
 468+ );
 469+ $addergroups = $wgUser->getEffectiveGroups();
 470+
 471+ foreach ( $addergroups as $addergroup ) {
 472+ $groups = array_merge_recursive(
 473+ $groups, $this->changeableByGroup( $addergroup )
 474+ );
 475+ $groups['add'] = array_unique( $groups['add'] );
 476+ $groups['remove'] = array_unique( $groups['remove'] );
 477+ $groups['add-self'] = array_unique( $groups['add-self'] );
 478+ $groups['remove-self'] = array_unique( $groups['remove-self'] );
 479+ }
 480+
 481+ // Run a hook because we can
 482+ wfRunHooks( 'UserrightsChangeableGroups', array( $this, $wgUser, $addergroups, &$groups ) );
 483+
 484+ return $groups;
 485+ }
 486+
 487+ /**
 488+ * Returns an array of the groups that a particular group can add/remove.
 489+ *
 490+ * @param $group String: the group to check for whether it can add/remove
 491+ * @return Array array( 'add' => array( addablegroups ), 'remove' => array( removablegroups ) , 'add-self' => array( addablegroups to self), 'remove-self' => array( removable groups from self) )
 492+ */
 493+ private function changeableByGroup( $group ) {
 494+ global $wgAddGroups, $wgRemoveGroups, $wgGroupsAddToSelf, $wgGroupsRemoveFromSelf;
 495+
 496+ $groups = array(
 497+ 'add' => array(),
 498+ 'remove' => array(),
 499+ 'add-self' => array(),
 500+ 'remove-self' => array()
 501+ );
 502+ if ( empty( $wgAddGroups[$group] ) ) {
 503+ // Don't add anything to $groups
 504+ } elseif ( $wgAddGroups[$group] === true ) {
 505+ // You get everything
 506+ $groups['add'] = User::getAllGroups();
 507+ } elseif ( is_array( $wgAddGroups[$group] ) ) {
 508+ $groups['add'] = $wgAddGroups[$group];
 509+ }
 510+
 511+ // Same thing for remove
 512+ if ( empty( $wgRemoveGroups[$group] ) ) {
 513+ } elseif ( $wgRemoveGroups[$group] === true ) {
 514+ $groups['remove'] = User::getAllGroups();
 515+ } elseif ( is_array( $wgRemoveGroups[$group] ) ) {
 516+ $groups['remove'] = $wgRemoveGroups[$group];
 517+ }
 518+
 519+ // Re-map numeric keys of AddToSelf/RemoveFromSelf to the 'user' key for backwards compatibility
 520+ if ( empty( $wgGroupsAddToSelf['user'] ) || $wgGroupsAddToSelf['user'] !== true ) {
 521+ foreach ( $wgGroupsAddToSelf as $key => $value ) {
 522+ if ( is_int( $key ) ) {
 523+ $wgGroupsAddToSelf['user'][] = $value;
 524+ }
 525+ }
 526+ }
 527+
 528+ if ( empty( $wgGroupsRemoveFromSelf['user'] ) || $wgGroupsRemoveFromSelf['user'] !== true ) {
 529+ foreach ( $wgGroupsRemoveFromSelf as $key => $value ) {
 530+ if ( is_int( $key ) ) {
 531+ $wgGroupsRemoveFromSelf['user'][] = $value;
 532+ }
 533+ }
 534+ }
 535+
 536+ // Now figure out what groups the user can add to him/herself
 537+ if ( empty( $wgGroupsAddToSelf[$group] ) ) {
 538+ } elseif ( $wgGroupsAddToSelf[$group] === true ) {
 539+ // No idea WHY this would be used, but it's there
 540+ $groups['add-self'] = User::getAllGroups();
 541+ } elseif ( is_array( $wgGroupsAddToSelf[$group] ) ) {
 542+ $groups['add-self'] = $wgGroupsAddToSelf[$group];
 543+ }
 544+
 545+ if ( empty( $wgGroupsRemoveFromSelf[$group] ) ) {
 546+ } elseif ( $wgGroupsRemoveFromSelf[$group] === true ) {
 547+ $groups['remove-self'] = User::getAllGroups();
 548+ } elseif ( is_array( $wgGroupsRemoveFromSelf[$group] ) ) {
 549+ $groups['remove-self'] = $wgGroupsRemoveFromSelf[$group];
 550+ }
 551+
 552+ return $groups;
 553+ }
 554+}
Property changes on: trunk/extensions/BatchUserRights/BatchUserRights_body.php
___________________________________________________________________
Added: svn:eol-style
1555 + native
Index: trunk/extensions/BatchUserRights/BatchUserRights.i18n.php
@@ -1,6 +1,6 @@
22 <?php
33 /**
4 - * Internationalisation file for the BatchUserRights extension.
 4+ * Internationalisation file for the BatchUserRights extension
55 *
66 * @file
77 * @ingroup Extensions
@@ -11,7 +11,7 @@
1212 /** English */
1313 $messages['en'] = array(
1414 'batchuserrights' => 'Batch user rights',
15 - 'batchuserrights-desc' => 'Allows adding one or more users to a group in one action',
 15+ 'batchuserrights-desc' => 'Allows adding one or more users to a group or more groups in one action',
1616 'batchuserrights-names' => 'Usernames to add this group to (one per line):',
1717 'batchuserrights-intro' => 'This page will let you add a group to multiple users at once.
1818 For security reasons, the list of addable groups is set in the extension configuration and cannot be changed from within the wiki.
@@ -102,7 +102,7 @@
103103 */
104104 $messages['de'] = array(
105105 'batchuserrights' => 'Massen-Benutzerrechte',
106 - 'batchuserrights-desc' => 'Einen oder mehrere Benutzer in einer Aktion einer Gruppe hinzufügen',
 106+ 'batchuserrights-desc' => 'Einen oder mehrere Benutzer in einer Aktion einer oder mehrerer Gruppe(n) hinzufügen',
107107 'batchuserrights-names' => 'Folgende Benutzer dieser Gruppe hinzufügen (einer pro Zeile):',
108108 'batchuserrights-intro' => 'Auf dieser Seite kannst du mehrere Benutzern gleichzeitig einer Gruppe hinzufügen.
109109 Aus Sicherheitsgründen ist die Liste der hinzufügbaren Gruppen in der Erweiterungs-Konfiguration festgelegt und kann im Wiki nicht verändert werden.
@@ -420,4 +420,3 @@
421421 'batchuserrights' => '批处理的用户权限',
422422 'batchuserrights-desc' => '允许将一个或多个用户添加到一个操作中的一个组',
423423 );
424 -
Index: trunk/extensions/BatchUserRights/BatchUserRights.php
@@ -35,5 +35,5 @@
3636 $dir = dirname( __FILE__ ) . '/';
3737 $wgExtensionMessagesFiles['BatchUserRights'] = $dir . 'BatchUserRights.i18n.php';
3838 $wgExtensionMessagesFiles['BatchUserRightsAliases'] = $dir . 'BatchUserRights.alias.php';
39 -$wgAutoloadClasses['SpecialBatchUserRights'] = $dir . 'SpecialBatchUserRights.php';
 39+$wgAutoloadClasses['SpecialBatchUserRights'] = $dir . 'BatchUserRights_body.php';
4040 $wgSpecialPages['BatchUserRights'] = 'SpecialBatchUserRights';

Follow-up revisions

RevisionCommit summaryAuthorDate
r107413r106556 reverts:...cervidae20:25, 27 December 2011

Comments

#Comment by Johnduhart (talk | contribs)   23:08, 23 December 2011
Renaming SpecialBatchUserRights.php to BatchUserRights_body.php

Please don't do that, we have a standard of file names being the class they contain.

#Comment by SVG (talk | contribs)   21:09, 27 December 2011

Changed class name in r107413

Status & tagging log