Index: trunk/extensions/Gadgets/Gadgets_body.php |
— | — | @@ -41,17 +41,21 @@ |
42 | 42 | |
43 | 43 | $options = array(); |
44 | 44 | foreach( $gadgets as $section => $thisSection ) { |
| 45 | + $available = array(); |
| 46 | + foreach( $thisSection as $gadget ) { |
| 47 | + if ( $gadget->isAllowed( $user ) ) { |
| 48 | + $gname = $gadget->getName(); |
| 49 | + $available[wfMsgExt( "gadget-$gname", 'parseinline' )] = $gname; |
| 50 | + } |
| 51 | + } |
45 | 52 | if ( $section !== '' ) { |
46 | 53 | $section = wfMsgExt( "gadget-section-$section", 'parseinline' ); |
47 | | - $options[$section] = array(); |
48 | | - $destination = &$options[$section]; |
| 54 | + if ( count ( $available ) ) { |
| 55 | + $options[$section] = $available; |
| 56 | + } |
49 | 57 | } else { |
50 | | - $destination = &$options; |
| 58 | + $options = array_merge( $options, $available ); |
51 | 59 | } |
52 | | - foreach( $thisSection as $gadget ) { |
53 | | - $gname = $gadget->getName(); |
54 | | - $destination[wfMsgExt( "gadget-$gname", 'parseinline' )] = $gname; |
55 | | - } |
56 | 60 | } |
57 | 61 | |
58 | 62 | $preferences['gadgets-intro'] = |
— | — | @@ -118,7 +122,7 @@ |
119 | 123 | $pages = array(); |
120 | 124 | |
121 | 125 | foreach ( $gadgets as $gadget ) { |
122 | | - if ( $gadget->isEnabled() ) { |
| 126 | + if ( $gadget->isEnabled( $wgUser ) && $gadget->isAllowed( $wgUser ) ) { |
123 | 127 | if ( $gadget->hasModule() ) { |
124 | 128 | $out->addModules( $gadget->getModuleName() ); |
125 | 129 | } |
— | — | @@ -183,7 +187,7 @@ |
184 | 188 | /** |
185 | 189 | * Increment this when changing class structure |
186 | 190 | */ |
187 | | - const GADGET_CLASS_VERSION = 2; |
| 191 | + const GADGET_CLASS_VERSION = 3; |
188 | 192 | |
189 | 193 | private $version = self::GADGET_CLASS_VERSION, |
190 | 194 | $scripts = array(), |
— | — | @@ -191,7 +195,8 @@ |
192 | 196 | $dependencies = array(), |
193 | 197 | $name, |
194 | 198 | $definition, |
195 | | - $resourceLoaded = false; |
| 199 | + $resourceLoaded = false, |
| 200 | + $requiredRights = array(); |
196 | 201 | |
197 | 202 | /** |
198 | 203 | * Creates an instance of this class from definition in MediaWiki:Gadgets-definition |
— | — | @@ -226,6 +231,9 @@ |
227 | 232 | case 'dependencies': |
228 | 233 | $gadget->dependencies = $params; |
229 | 234 | break; |
| 235 | + case 'rights': |
| 236 | + $gadget->requiredRights = $params; |
| 237 | + break; |
230 | 238 | } |
231 | 239 | } |
232 | 240 | foreach ( preg_split( '/\s*\|\s*/', $m[3], -1, PREG_SPLIT_NO_EMPTY ) as $page ) { |
— | — | @@ -262,14 +270,26 @@ |
263 | 271 | } |
264 | 272 | |
265 | 273 | /** |
266 | | - * @return Boolean: Whether this gadget is enabled for current user |
| 274 | + * Checks whether this gadget is enabled for given user |
| 275 | + * |
| 276 | + * @param $user User: user to check against |
| 277 | + * @return Boolean |
267 | 278 | */ |
268 | | - public function isEnabled() { |
269 | | - global $wgUser; |
270 | | - return (bool)$wgUser->getOption( "gadget-{$this->name}" ); |
| 279 | + public function isEnabled( $user ) { |
| 280 | + return (bool)$user->getOption( "gadget-{$this->name}" ); |
271 | 281 | } |
272 | 282 | |
273 | 283 | /** |
| 284 | + * Checks whether given user has permissions to use this gadget |
| 285 | + * |
| 286 | + * @param $user User: user to check against |
| 287 | + * @return Boolean |
| 288 | + */ |
| 289 | + public function isAllowed( $user ) { |
| 290 | + return count( array_intersect( $this->requiredRights, $user->getRights() ) ) == count( $this->requiredRights ); |
| 291 | + } |
| 292 | + |
| 293 | + /** |
274 | 294 | * @return Boolean: Whether all of this gadget's JS components support ResourceLoader |
275 | 295 | */ |
276 | 296 | public function supportsResourceLoader() { |
— | — | @@ -354,6 +374,14 @@ |
355 | 375 | } |
356 | 376 | |
357 | 377 | /** |
| 378 | + * Returns array of permissions required by this gadget |
| 379 | + * @return Array |
| 380 | + */ |
| 381 | + public function getRequiredRights() { |
| 382 | + return $this->requiredRights; |
| 383 | + } |
| 384 | + |
| 385 | + /** |
358 | 386 | * Loads and returns a list of all gadgets |
359 | 387 | * @return Mixed: Array of gadgets or false |
360 | 388 | */ |
Index: trunk/extensions/Gadgets/Gadgets.i18n.php |
— | — | @@ -33,6 +33,7 @@ |
34 | 34 | 'gadgets-pagetext' => "Below is a list of special gadgets users can enable on their [[Special:Preferences|preferences page]], as defined by the [[MediaWiki:Gadgets-definition|definitions]]. |
35 | 35 | This overview provides easy access to the system message pages that define each gadget's description and code.", |
36 | 36 | 'gadgets-uses' => 'Uses', |
| 37 | + 'gadgets-required-rights' => 'Requires the {{PLURAL:$2|$1 right|following rights: $1}}.', |
37 | 38 | 'gadgets-export' => 'Export', |
38 | 39 | 'gadgets-export-title' => 'Gadget export', |
39 | 40 | 'gadgets-not-found' => 'Gadget "$1" not found.', |
Index: trunk/extensions/Gadgets/SpecialGadgets.php |
— | — | @@ -114,6 +114,12 @@ |
115 | 115 | $lnk[] = $skin->link( $t, htmlspecialchars( $t->getText() ) ); |
116 | 116 | } |
117 | 117 | $wgOut->addHTML( $wgLang->commaList( $lnk ) ); |
| 118 | + $rights = $gadget->getRequiredRights(); |
| 119 | + if ( count( $rights ) ) { |
| 120 | + $wgOut->addHTML( '<br />' ); |
| 121 | + $wgOut->addWikiMsg( 'gadgets-required-rights', $wgLang->commaList( $rights ), count( $rights ) ); |
| 122 | + } |
| 123 | + |
118 | 124 | $wgOut->addHTML( Xml::closeElement( 'li' ) . "\n" ); |
119 | 125 | } |
120 | 126 | } |
Index: trunk/extensions/Gadgets/Gadgets_tests.php |
— | — | @@ -43,4 +43,24 @@ |
44 | 44 | $this->assertTrue( $g->supportsResourceLoader() ); |
45 | 45 | $this->assertEquals( array( 'jquery.ui' ), $g->getDependencies() ); |
46 | 46 | } |
| 47 | + |
| 48 | + function testPreferences() { |
| 49 | + global $wgUser, $wgOut; |
| 50 | + $prefs = array(); |
| 51 | + $wgOut->setTitle( Title::newFromText( 'test' ) ); |
| 52 | + |
| 53 | + Gadget::loadStructuredList( '* foo | foo.js |
| 54 | +==keep-section1== |
| 55 | +* bar| bar.js |
| 56 | +==remove-section== |
| 57 | +* baz [rights=embezzle] |baz.js |
| 58 | +==keep-section2== |
| 59 | +* quux [rights=read] | quux.js' ); |
| 60 | + $this->assertTrue( GadgetHooks::getPreferences( $wgUser, $prefs ), 'GetPrefences hook should return true' ); |
| 61 | + |
| 62 | + $options = $prefs['gadgets']['options']; |
| 63 | + $this->assertFalse( isset( $options['<gadget-section-remove-section>'] ), 'Must not show empty sections' ); |
| 64 | + $this->assertTrue( isset( $options['<gadget-section-keep-section1>'] ) ); |
| 65 | + $this->assertTrue( isset( $options['<gadget-section-keep-section2>'] ) ); |
| 66 | + } |
47 | 67 | } |
\ No newline at end of file |