| Index: branches/RL2/extensions/Gadgets/GadgetHooks.php |
| — | — | @@ -1,431 +0,0 @@ |
| 2 | | -<?php |
| 3 | | -/** |
| 4 | | - * Gadgets extension - lets users select custom javascript gadgets |
| 5 | | - * |
| 6 | | - * |
| 7 | | - * For more info see http://mediawiki.org/wiki/Extension:Gadgets |
| 8 | | - * |
| 9 | | - * @file |
| 10 | | - * @ingroup Extensions |
| 11 | | - * @author Daniel Kinzler, brightbyte.de |
| 12 | | - * @copyright © 2007 Daniel Kinzler |
| 13 | | - * @license GNU General Public Licence 2.0 or later |
| 14 | | - */ |
| 15 | | - |
| 16 | | -class GadgetHooks { |
| 17 | | - /** |
| 18 | | - * Get the gadget ID from a title |
| 19 | | - * @param $title Title object |
| 20 | | - * @return string Gadget id or null if not a gadget definition page |
| 21 | | - */ |
| 22 | | - public static function getIDFromTitle( Title $title ) { |
| 23 | | - $id = $title->getText(); |
| 24 | | - if ( $title->getNamespace() !== NS_GADGET_DEFINITION || !preg_match( '!\.js$!u', $id ) ) { |
| 25 | | - // Not a gadget definition page |
| 26 | | - return null; |
| 27 | | - } |
| 28 | | - // Trim .js from the page name to obtain the gadget ID |
| 29 | | - return substr( $id, 0, -3 ); |
| 30 | | - } |
| 31 | | - |
| 32 | | - /** |
| 33 | | - * Get a Title object of the gadget definition page from a gadget id |
| 34 | | - * @param $is String |
| 35 | | - * @return Title|null |
| 36 | | - */ |
| 37 | | - public static function getDefinitionTitleFromID( $id ) { |
| 38 | | - return Title::makeTitleSafe( NS_GADGET_DEFINITION, $id . '.js' ); |
| 39 | | - } |
| 40 | | - |
| 41 | | - /** |
| 42 | | - * ArticleDeleteComplete hook handler. |
| 43 | | - * |
| 44 | | - * @param $article Article |
| 45 | | - * @param $user User |
| 46 | | - * @param $reason String: Deletion summary |
| 47 | | - * @param $id Int: Page ID |
| 48 | | - */ |
| 49 | | - public static function gadgetDefinitionDelete( $article, $user, $reason, $id ) { |
| 50 | | - $id = self::getIDFromTitle( $article->getTitle() ); |
| 51 | | - if ( !$id ) { |
| 52 | | - return true; |
| 53 | | - } |
| 54 | | - |
| 55 | | - $repo = LocalGadgetRepo::singleton(); |
| 56 | | - $repo->deleteGadget( $id ); |
| 57 | | - // deleteGadget() may return an error if the Gadget didn't exist, but we don't care here |
| 58 | | - return true; |
| 59 | | - } |
| 60 | | - |
| 61 | | - /** |
| 62 | | - * ArticleSaveComplete hook handler. |
| 63 | | - * |
| 64 | | - * @param $article Article |
| 65 | | - * @param $user User |
| 66 | | - * @param $text String: New page text |
| 67 | | - * @param $summary String: Edit summary |
| 68 | | - * @param $isMinor Bool: Whether this was a minor edit |
| 69 | | - * @param $isWatch unused |
| 70 | | - * @param $section unused |
| 71 | | - * @param $flags: Int: Bitmap of flags passed to WikiPage::doEdit() |
| 72 | | - * @param $revision: Revision object for the new revision |
| 73 | | - */ |
| 74 | | - public static function gadgetDefinitionSave( $article, $user, $text, $summary, $isMinor, |
| 75 | | - $isWatch, $section, $flags, $revision ) |
| 76 | | - { |
| 77 | | - $id = self::getIDFromTitle( $article->getTitle() ); |
| 78 | | - if ( !$id ) { |
| 79 | | - return true; |
| 80 | | - } |
| 81 | | - |
| 82 | | - $previousRev = $revision->getPrevious(); |
| 83 | | - $prevTs = $previousRev instanceof Revision ? $previousRev->getTimestamp() : wfTimestampNow(); |
| 84 | | - |
| 85 | | - // Update the database entry for this gadget |
| 86 | | - $repo = LocalGadgetRepo::singleton(); |
| 87 | | - // TODO: Timestamp in the constructor is ugly |
| 88 | | - $gadget = new Gadget( $id, $repo, $text, $prevTs ); |
| 89 | | - $repo->modifyGadget( $gadget, $revision->getTimestamp() ); |
| 90 | | - |
| 91 | | - // modifyGadget() returns a Status object with an error if there was a conflict, |
| 92 | | - // but we don't care. If a conflict occurred, that must be because a newer edit's |
| 93 | | - // DB update occurred before ours, in which case the right thing to do is to occu |
| 94 | | - |
| 95 | | - return true; |
| 96 | | - } |
| 97 | | - |
| 98 | | - /** |
| 99 | | - * Update the database entry for a gadget if the description page is |
| 100 | | - * newer than the database entry. |
| 101 | | - * @param $title Title object |
| 102 | | - */ |
| 103 | | - public static function gadgetDefinitionUpdateIfChanged( $title ) { |
| 104 | | - $id = self::getIDFromTitle( $title ); |
| 105 | | - if ( !$id ) { |
| 106 | | - return; |
| 107 | | - } |
| 108 | | - |
| 109 | | - // Check whether this undeletion changed the latest revision of the page, by comparing |
| 110 | | - // the timestamp of the latest revision with the timestamp in the DB |
| 111 | | - $repo = LocalGadgetRepo::singleton(); |
| 112 | | - $gadget = $repo->getGadget( $id ); |
| 113 | | - $gadgetTS = $gadget ? $gadget->getTimestamp() : 0; |
| 114 | | - |
| 115 | | - $rev = Revision::newFromTitle( $title ); |
| 116 | | - if ( wfTimestamp( TS_MW, $rev->getTimestamp() ) === |
| 117 | | - wfTimestamp( TS_MW, $gadgetTS ) ) { |
| 118 | | - // The latest rev didn't change. Someone must've undeleted an older revision |
| 119 | | - return; |
| 120 | | - } |
| 121 | | - |
| 122 | | - // Update the database entry for this gadget |
| 123 | | - $newGadget = new Gadget( $id, $repo, $rev->getRawText(), $gadgetTS ); |
| 124 | | - $repo->modifyGadget( $newGadget, $rev->getTimestamp() ); |
| 125 | | - |
| 126 | | - // modifyGadget() returns a Status object with an error if there was a conflict, |
| 127 | | - // but we do't care, see similar comment in articleSaveComplete() |
| 128 | | - return; |
| 129 | | - } |
| 130 | | - |
| 131 | | - /** |
| 132 | | - * ArticleUndelete hook handler |
| 133 | | - * @param $title Title object |
| 134 | | - * @param $created Bool: Whether this undeletion recreated the page |
| 135 | | - * @param $comment String: Undeletion summary |
| 136 | | - */ |
| 137 | | - public static function gadgetDefinitionUndelete( $title, $created, $comment ) { |
| 138 | | - self::gadgetDefinitionUpdateIfChanged( $title ); |
| 139 | | - return true; |
| 140 | | - } |
| 141 | | - |
| 142 | | - public static function gadgetDefinitionImport( $title, $origTitle, $revCount, $sRevCount, $pageInfo ) { |
| 143 | | - self::gadgetDefinitionUpdateIfChanged( $title ); |
| 144 | | - return true; |
| 145 | | - } |
| 146 | | - |
| 147 | | - /** |
| 148 | | - * ArticleDeleteComplete hook handler. |
| 149 | | - * |
| 150 | | - * @param $article Article |
| 151 | | - * @param $user User |
| 152 | | - * @param $reason String: Deletion summary |
| 153 | | - * @param $id Int: Page ID |
| 154 | | - */ |
| 155 | | - public static function cssJsPageDelete( $article, $user, $reason, $id ) { |
| 156 | | - GadgetPageList::delete( $article->getTitle() ); |
| 157 | | - return true; |
| 158 | | - } |
| 159 | | - |
| 160 | | - /** |
| 161 | | - * ArticleSaveComplete hook handler. |
| 162 | | - * |
| 163 | | - * @param $article Article |
| 164 | | - * @param $user User |
| 165 | | - * @param $text String: New page text |
| 166 | | - * @param $summary String: Edit summary |
| 167 | | - * @param $isMinor Bool: Whether this was a minor edit |
| 168 | | - * @param $isWatch unused |
| 169 | | - * @param $section unused |
| 170 | | - * @param $flags: Int: Bitmap of flags passed to WikiPage::doEdit() |
| 171 | | - * @param $revision: Revision object for the new revision |
| 172 | | - */ |
| 173 | | - public static function cssOrJsPageSave( $article, $user, $text, $summary, $isMinor, |
| 174 | | - $isWatch, $section, $flags, $revision ) |
| 175 | | - { |
| 176 | | - $title = $article->getTitle(); |
| 177 | | - GadgetPageList::updatePageStatus( $title ); |
| 178 | | - return true; |
| 179 | | - } |
| 180 | | - |
| 181 | | - /** |
| 182 | | - * ArticleUndelete hook handler |
| 183 | | - * @param $title Title object |
| 184 | | - * @param $created Bool: Whether this undeletion recreated the page |
| 185 | | - * @param $comment String: Undeletion summary |
| 186 | | - */ |
| 187 | | - public static function cssOrJsPageUndelete( $title, $created, $comment ) { |
| 188 | | - GadgetPageList::updatePageStatus( $title ); |
| 189 | | - return true; |
| 190 | | - } |
| 191 | | - |
| 192 | | - public static function cssOrJsPageMove( $oldTitle, $newTitle, $user, $pageid, $redirid ) { |
| 193 | | - // Delete the old title from the list. Even if it still exists after the move, |
| 194 | | - // it'll be a redirect and we don't want those in there |
| 195 | | - GadgetPageList::delete( $oldTitle ); |
| 196 | | - |
| 197 | | - GadgetPageList::updatePageStatus( $newTitle ); |
| 198 | | - return true; |
| 199 | | - } |
| 200 | | - |
| 201 | | - /** |
| 202 | | - * UserGetDefaultOptions hook handler |
| 203 | | - * @param $defaultOptions Array of default preference keys and values |
| 204 | | - */ |
| 205 | | - public static function userGetDefaultOptions( &$defaultOptions ) { |
| 206 | | - $repo = LocalGadgetRepo::singleton(); |
| 207 | | - $gadgetIds = $repo->getGadgetIds(); |
| 208 | | - foreach ( $gadgetIds as $gadgetId ) { |
| 209 | | - $gadget = $repo->getGadget( $gadgetId ); |
| 210 | | - if ( $gadget->isEnabledByDefault() ) { |
| 211 | | - $defaultOptions['gadget-' . $gadget->getId()] = 1; |
| 212 | | - } |
| 213 | | - } |
| 214 | | - return true; |
| 215 | | - } |
| 216 | | - |
| 217 | | - /** |
| 218 | | - * GetPreferences hook handler. |
| 219 | | - * @param $user User |
| 220 | | - * @param $preferences Array: Preference descriptions |
| 221 | | - */ |
| 222 | | - public static function getPreferences( $user, &$preferences ) { |
| 223 | | - $repo = LocalGadgetRepo::singleton(); |
| 224 | | - $gadgets = $repo->getGadgetIds(); |
| 225 | | - $categories = array(); // array( category => array( desc => title ) ) |
| 226 | | - $default = array(); // array of Gadget ids |
| 227 | | - foreach ( $gadgets as $id ) { |
| 228 | | - $gadget = $repo->getGadget( $id ); |
| 229 | | - if ( !$gadget->isAllowed( $user ) || $gadget->isHidden() ) { |
| 230 | | - continue; |
| 231 | | - } |
| 232 | | - $category = $gadget->getCategory(); |
| 233 | | - |
| 234 | | - // Add the Gadget to the right category |
| 235 | | - $title = htmlspecialchars( $gadget->getTitleMessage() ); |
| 236 | | - $description = $gadget->getDescriptionMessage(); // Is parsed, doesn't need escaping |
| 237 | | - if ( $description === '' ) { |
| 238 | | - // Empty description, just use the title |
| 239 | | - $text = $title; |
| 240 | | - } else { |
| 241 | | - $text = wfMessage( 'gadgets-preference-description' )->rawParams( $title, $description )->parse(); |
| 242 | | - } |
| 243 | | - $categories[$category][$text] = $id; |
| 244 | | - // Add the Gadget to the default list if enabled |
| 245 | | - if ( $gadget->isEnabledForUser( $user ) ) { |
| 246 | | - $default[] = $id; |
| 247 | | - } |
| 248 | | - } |
| 249 | | - |
| 250 | | - $options = array(); // array( desc1 => gadget1, category1 => array( desc2 => gadget2 ) ) |
| 251 | | - foreach ( $categories as $category => $gadgets ) { |
| 252 | | - if ( $category !== '' ) { |
| 253 | | - $categoryMsg = htmlspecialchars( $repo->getCategoryTitle( $category ) ); |
| 254 | | - $options[$categoryMsg] = $gadgets; |
| 255 | | - } else { |
| 256 | | - $options += $gadgets; |
| 257 | | - } |
| 258 | | - } |
| 259 | | - |
| 260 | | - $preferences['gadgets-intro'] = |
| 261 | | - array( |
| 262 | | - 'type' => 'info', |
| 263 | | - 'label' => ' ', |
| 264 | | - 'default' => Xml::tags( 'tr', array(), |
| 265 | | - Xml::tags( 'td', array( 'colspan' => 2 ), |
| 266 | | - wfMsgExt( 'gadgets-prefstext', 'parse' ) ) ), |
| 267 | | - 'section' => 'gadgets', |
| 268 | | - 'raw' => 1, |
| 269 | | - 'rawrow' => 1, |
| 270 | | - ); |
| 271 | | - $preferences['gadgets'] = |
| 272 | | - array( |
| 273 | | - 'type' => 'multiselect', |
| 274 | | - 'options' => $options, |
| 275 | | - 'section' => 'gadgets', |
| 276 | | - 'label' => ' ', |
| 277 | | - 'prefix' => 'gadget-', |
| 278 | | - 'default' => $default, |
| 279 | | - ); |
| 280 | | - |
| 281 | | - // Add tab for shared gadgets |
| 282 | | - $preferences['gadgets-intro-shared'] = |
| 283 | | - array( |
| 284 | | - 'type' => 'info', |
| 285 | | - 'label' => ' ', |
| 286 | | - 'default' => Xml::tags( 'tr', array(), |
| 287 | | - Xml::tags( 'td', array( 'colspan' => 2 ), |
| 288 | | - wfMsgExt( 'gadgets-sharedprefstext', 'parse' ) ) ), |
| 289 | | - 'section' => 'gadgets-shared', |
| 290 | | - 'raw' => 1, |
| 291 | | - 'rawrow' => 1, |
| 292 | | - ); |
| 293 | | - $preferences['gadgets-shared'] = |
| 294 | | - array( |
| 295 | | - 'type' => 'multiselect', |
| 296 | | - 'options' => array(), // TODO: Maybe fill in stuff anyway? The backend may need that |
| 297 | | - 'section' => 'gadgets-shared', |
| 298 | | - 'label' => ' ', |
| 299 | | - 'prefix' => 'gadget-', |
| 300 | | - 'default' => array(), |
| 301 | | - ); |
| 302 | | - return true; |
| 303 | | - } |
| 304 | | - |
| 305 | | - /** |
| 306 | | - * ResourceLoaderRegisterModules hook handler. |
| 307 | | - * @param $resourceLoader ResourceLoader |
| 308 | | - */ |
| 309 | | - public static function registerModules( &$resourceLoader ) { |
| 310 | | - $gadgets = GadgetRepo::getAllGadgets(); |
| 311 | | - foreach ( $gadgets as $gadget ) { |
| 312 | | - $resourceLoader->register( $gadget->getModuleName(), $gadget->getModule() ); |
| 313 | | - } |
| 314 | | - return true; |
| 315 | | - } |
| 316 | | - |
| 317 | | - /** |
| 318 | | - * BeforePageDisplay hook handler. |
| 319 | | - * @param $out OutputPage |
| 320 | | - */ |
| 321 | | - public static function beforePageDisplay( $out ) { |
| 322 | | - wfProfileIn( __METHOD__ ); |
| 323 | | - |
| 324 | | - $user = $out->getUser(); |
| 325 | | - $gadgets = GadgetRepo::getAllGadgets(); |
| 326 | | - foreach ( $gadgets as $gadget ) { |
| 327 | | - if ( $gadget->isEnabledForUser( $user ) && $gadget->isAllowed( $user ) ) { |
| 328 | | - $out->addModules( $gadget->getModuleName() ); |
| 329 | | - } |
| 330 | | - } |
| 331 | | - |
| 332 | | - // Add preferences JS if we're on Special:Preferences |
| 333 | | - if ( $out->getTitle()->equals( SpecialPage::getTitleFor( 'Preferences' ) ) ) { |
| 334 | | - $out->addModules( 'ext.gadgets.preferences' ); |
| 335 | | - } |
| 336 | | - |
| 337 | | - wfProfileOut( __METHOD__ ); |
| 338 | | - return true; |
| 339 | | - } |
| 340 | | - |
| 341 | | - /** |
| 342 | | - * MakeGlobalVariablesScript hook handler |
| 343 | | - * @param $vars Array: Key/value pars for mw.config.set on this page. |
| 344 | | - * @param $out OutputPage |
| 345 | | - */ |
| 346 | | - public static function makeGlobalVariablesScript( &$vars, $out ) { |
| 347 | | - $title = $out->getTitle(); |
| 348 | | - $user = $out->getUser(); |
| 349 | | - // FIXME: This is not a nice way to do it. Maybe we should check for the presence |
| 350 | | - // of a module instead or something. |
| 351 | | - if ( $title->equals( SpecialPage::getTitleFor( 'Gadgets' ) ) || |
| 352 | | - $title->equals( SpecialPage::getTitleFor( 'Preferences' ) ) ) |
| 353 | | - { |
| 354 | | - global $wgGadgetEnableSharing; |
| 355 | | - |
| 356 | | - // Pass the source data for each source that is used by a repository |
| 357 | | - $repos = GadgetRepo::getAllRepos(); |
| 358 | | - $sources = $out->getResourceLoader()->getSources(); |
| 359 | | - $repoData = array(); |
| 360 | | - foreach ( $repos as $repo ) { |
| 361 | | - $repoData[$repo->getSource()] = $sources[$repo->getSource()]; |
| 362 | | - } |
| 363 | | - |
| 364 | | - $vars['gadgetsConf'] = array( |
| 365 | | - 'enableSharing' => $wgGadgetEnableSharing, |
| 366 | | - 'allRights' => User::getAllRights(), |
| 367 | | - 'repos' => $repoData, |
| 368 | | - 'userIsAllowed' => array( |
| 369 | | - 'editinterface' => $user->isAllowed( 'editinterface' ), |
| 370 | | - 'gadgets-definition-create' => $user->isAllowed( 'gadgets-definition-create' ), |
| 371 | | - 'gadgets-definition-edit' => $user->isAllowed( 'gadgets-definition-edit' ), |
| 372 | | - 'gadgets-definition-delete' => $user->isAllowed( 'gadgets-definition-delete' ), |
| 373 | | - ), |
| 374 | | - ); |
| 375 | | - } |
| 376 | | - return true; |
| 377 | | - } |
| 378 | | - |
| 379 | | - /** |
| 380 | | - * UnitTestsList hook handler |
| 381 | | - * @param $files Array: List of extension test files |
| 382 | | - */ |
| 383 | | - public static function unitTestsList( &$files ) { |
| 384 | | - $files[] = dirname( __FILE__ ) . '/tests/GadgetsTest.php'; |
| 385 | | - return true; |
| 386 | | - } |
| 387 | | - |
| 388 | | - public static function loadExtensionSchemaUpdates( $updater ) { |
| 389 | | - $dir = dirname( __FILE__ ); |
| 390 | | - $updater->addExtensionUpdate( array( 'addtable', 'gadgets', "$dir/sql/gadgets.sql", true ) ); |
| 391 | | - $updater->addExtensionUpdate( array( 'addtable', 'gadgetpagelist', "$dir/sql/patch-gadgetpagelist.sql", true ) ); |
| 392 | | - return true; |
| 393 | | - } |
| 394 | | - |
| 395 | | - public static function canonicalNamespaces( &$list ) { |
| 396 | | - $list[NS_GADGET] = 'Gadget'; |
| 397 | | - $list[NS_GADGET_TALK] = 'Gadget_talk'; |
| 398 | | - $list[NS_GADGET_DEFINITION] = 'Gadget_definition'; |
| 399 | | - $list[NS_GADGET_DEFINITION_TALK] = 'Gadget_definition_talk'; |
| 400 | | - return true; |
| 401 | | - } |
| 402 | | - |
| 403 | | - public static function titleIsCssOrJsPage( $title, &$result ) { |
| 404 | | - if ( ( $title->getNamespace() == NS_GADGET || $title->getNamespace() == NS_GADGET_DEFINITION ) && |
| 405 | | - preg_match( '!\.(css|js)$!u', $title->getText() ) ) |
| 406 | | - { |
| 407 | | - $result = true; |
| 408 | | - } |
| 409 | | - return true; |
| 410 | | - } |
| 411 | | - |
| 412 | | - public static function titleIsMovable( $title, &$result ) { |
| 413 | | - if ( $title->getNamespace() == NS_GADGET_DEFINITION ) { |
| 414 | | - $result = false; |
| 415 | | - } |
| 416 | | - return true; |
| 417 | | - } |
| 418 | | - |
| 419 | | - public static function getUserPermissionsErrors( $title, $user, $action, &$result ) { |
| 420 | | - if ( $title->getNamespace() == NS_GADGET_DEFINITION ) { |
| 421 | | - // Enforce restrictions on the Gadget_definition namespace |
| 422 | | - if ( $action == 'create' && !$user->isAllowed( 'gadgets-definition-create' ) ) { |
| 423 | | - $result[] = array( 'gadgets-cant-create' ); |
| 424 | | - return false; |
| 425 | | - } elseif ( $action == 'delete' && !$user->isAllowed( 'gadgets-definition-delete' ) ) { |
| 426 | | - $result[] = array( 'gadgets-cant-delete' ); |
| 427 | | - return false; |
| 428 | | - } |
| 429 | | - } |
| 430 | | - return true; |
| 431 | | - } |
| 432 | | -} |
| Index: branches/RL2/extensions/Gadgets/tests/GadgetsTest.php |
| — | — | @@ -68,7 +68,7 @@ |
| 69 | 69 | * baz [rights=embezzle] |baz.js |
| 70 | 70 | ==keep-section2== |
| 71 | 71 | * quux [rights=read] | quux.js' ); |
| 72 | | - $this->assertTrue( GadgetHooks::getPreferences( $wgUser, $prefs ), 'GetPrefences hook should return true' ); |
| | 72 | + $this->assertTrue( GadgetsHooks::getPreferences( $wgUser, $prefs ), 'GetPrefences hook should return true' ); |
| 73 | 73 | |
| 74 | 74 | $options = $prefs['gadgets']['options']; |
| 75 | 75 | $this->assertFalse( isset( $options['<gadget-section-remove-section>'] ), 'Must not show empty sections' ); |
| Index: branches/RL2/extensions/Gadgets/Gadgets.php |
| — | — | @@ -95,25 +95,25 @@ |
| 96 | 96 | #$wgGroupPermissions['gadgetmanagers']['gadgets-definition-edit'] = true; |
| 97 | 97 | #$wgGroupPermissions['gadgetmanagers']['gadgets-definition-delete'] = true; |
| 98 | 98 | |
| 99 | | -$wgHooks['AfterImportPage'][] = 'GadgetHooks::gadgetDefinitionImport'; |
| 100 | | -$wgHooks['ArticleDeleteComplete'][] = 'GadgetHooks::gadgetDefinitionDelete'; |
| 101 | | -$wgHooks['ArticleDeleteComplete'][] = 'GadgetHooks::cssJsPageDelete'; |
| 102 | | -$wgHooks['ArticleSaveComplete'][] = 'GadgetHooks::gadgetDefinitionSave'; |
| 103 | | -$wgHooks['ArticleSaveComplete'][] = 'GadgetHooks::cssOrJsPageSave'; |
| 104 | | -$wgHooks['ArticleUndelete'][] = 'GadgetHooks::gadgetDefinitionUndelete'; |
| 105 | | -$wgHooks['ArticleUndelete'][] = 'GadgetHooks::cssOrJsPageUndelete'; |
| 106 | | -$wgHooks['BeforePageDisplay'][] = 'GadgetHooks::beforePageDisplay'; |
| 107 | | -$wgHooks['MakeGlobalVariablesScript'][] = 'GadgetHooks::makeGlobalVariablesScript'; |
| 108 | | -$wgHooks['CanonicalNamespaces'][] = 'GadgetHooks::canonicalNamespaces'; |
| 109 | | -$wgHooks['GetPreferences'][] = 'GadgetHooks::getPreferences'; |
| 110 | | -$wgHooks['UserGetDefaultOptions'][] = 'GadgetHooks::userGetDefaultOptions'; |
| 111 | | -$wgHooks['LoadExtensionSchemaUpdates'][] = 'GadgetHooks::loadExtensionSchemaUpdates'; |
| 112 | | -$wgHooks['ResourceLoaderRegisterModules'][] = 'GadgetHooks::registerModules'; |
| 113 | | -$wgHooks['TitleIsCssOrJsPage'][] = 'GadgetHooks::titleIsCssOrJsPage'; |
| 114 | | -$wgHooks['TitleIsMovable'][] = 'GadgetHooks::titleIsMovable'; |
| 115 | | -$wgHooks['TitleMoveComplete'][] = 'GadgetHooks::cssOrJsPageMove'; |
| 116 | | -$wgHooks['getUserPermissionsErrors'][] = 'GadgetHooks::getUserPermissionsErrors'; |
| 117 | | -#$wgHooks['UnitTestsList'][] = 'GadgetHooks::unitTestsList'; // FIXME: broken |
| | 99 | +$wgHooks['AfterImportPage'][] = 'GadgetsHooks::gadgetDefinitionImport'; |
| | 100 | +$wgHooks['ArticleDeleteComplete'][] = 'GadgetsHooks::gadgetDefinitionDelete'; |
| | 101 | +$wgHooks['ArticleDeleteComplete'][] = 'GadgetsHooks::cssJsPageDelete'; |
| | 102 | +$wgHooks['ArticleSaveComplete'][] = 'GadgetsHooks::gadgetDefinitionSave'; |
| | 103 | +$wgHooks['ArticleSaveComplete'][] = 'GadgetsHooks::cssOrJsPageSave'; |
| | 104 | +$wgHooks['ArticleUndelete'][] = 'GadgetsHooks::gadgetDefinitionUndelete'; |
| | 105 | +$wgHooks['ArticleUndelete'][] = 'GadgetsHooks::cssOrJsPageUndelete'; |
| | 106 | +$wgHooks['BeforePageDisplay'][] = 'GadgetsHooks::beforePageDisplay'; |
| | 107 | +$wgHooks['MakeGlobalVariablesScript'][] = 'GadgetsHooks::makeGlobalVariablesScript'; |
| | 108 | +$wgHooks['CanonicalNamespaces'][] = 'GadgetsHooks::canonicalNamespaces'; |
| | 109 | +$wgHooks['GetPreferences'][] = 'GadgetsHooks::getPreferences'; |
| | 110 | +$wgHooks['UserGetDefaultOptions'][] = 'GadgetsHooks::userGetDefaultOptions'; |
| | 111 | +$wgHooks['LoadExtensionSchemaUpdates'][] = 'GadgetsHooks::loadExtensionSchemaUpdates'; |
| | 112 | +$wgHooks['ResourceLoaderRegisterModules'][] = 'GadgetsHooks::registerModules'; |
| | 113 | +$wgHooks['TitleIsCssOrJsPage'][] = 'GadgetsHooks::titleIsCssOrJsPage'; |
| | 114 | +$wgHooks['TitleIsMovable'][] = 'GadgetsHooks::titleIsMovable'; |
| | 115 | +$wgHooks['TitleMoveComplete'][] = 'GadgetsHooks::cssOrJsPageMove'; |
| | 116 | +$wgHooks['getUserPermissionsErrors'][] = 'GadgetsHooks::getUserPermissionsErrors'; |
| | 117 | +#$wgHooks['UnitTestsList'][] = 'GadgetsHooks::unitTestsList'; // FIXME: broken |
| 118 | 118 | |
| 119 | 119 | $dir = dirname(__FILE__) . '/'; |
| 120 | 120 | $wgExtensionMessagesFiles['Gadgets'] = $dir . 'Gadgets.i18n.php'; |
| — | — | @@ -125,7 +125,7 @@ |
| 126 | 126 | $wgAutoloadClasses['ApiQueryGadgets'] = $dir . 'api/ApiQueryGadgets.php'; |
| 127 | 127 | $wgAutoloadClasses['ForeignDBGadgetRepo'] = $dir . 'backend/ForeignDBGadgetRepo.php'; |
| 128 | 128 | $wgAutoloadClasses['Gadget'] = $dir . 'backend/Gadget.php'; |
| 129 | | -$wgAutoloadClasses['GadgetHooks'] = $dir . 'GadgetHooks.php'; |
| | 129 | +$wgAutoloadClasses['GadgetsHooks'] = $dir . 'Gadgets.hooks.php'; |
| 130 | 130 | $wgAutoloadClasses['GadgetPageList'] = $dir . 'backend/GadgetPageList.php'; |
| 131 | 131 | $wgAutoloadClasses['GadgetRepo'] = $dir . 'backend/GadgetRepo.php'; |
| 132 | 132 | $wgAutoloadClasses['GadgetResourceLoaderModule'] = $dir . 'backend/GadgetResourceLoaderModule.php'; |
| Index: branches/RL2/extensions/Gadgets/SpecialGadgets.php |
| — | — | @@ -124,7 +124,7 @@ |
| 125 | 125 | ); |
| 126 | 126 | if ( $user->isAllowed( 'gadgets-definition-edit' ) ) { |
| 127 | 127 | $extra[] = Linker::link( |
| 128 | | - GadgetHooks::getDefinitionTitleFromID( $gadget->getId() ), |
| | 128 | + GadgetsHooks::getDefinitionTitleFromID( $gadget->getId() ), |
| 129 | 129 | wfMessage( 'gadgets-gadget-modify' )->escaped(), |
| 130 | 130 | array( |
| 131 | 131 | 'title' => wfMessage( 'gadgets-gadget-modify-tooltip' )->plain(), |
| — | — | @@ -136,7 +136,7 @@ |
| 137 | 137 | |
| 138 | 138 | if ( $user->isAllowed( 'gadgets-definition-delete' ) ) { |
| 139 | 139 | $extra[] = Linker::link( |
| 140 | | - GadgetHooks::getDefinitionTitleFromID( $gadget->getId() ), |
| | 140 | + GadgetsHooks::getDefinitionTitleFromID( $gadget->getId() ), |
| 141 | 141 | wfMessage( 'gadgets-gadget-delete' )->escaped(), |
| 142 | 142 | array( |
| 143 | 143 | 'title' => wfMessage( 'gadgets-gadget-delete-tooltip' )->plain(), |
| — | — | @@ -327,7 +327,7 @@ |
| 328 | 328 | $exportTitles = array(); |
| 329 | 329 | |
| 330 | 330 | // NS_GADGET_DEFINITION page of this gadget |
| 331 | | - $exportTitles[] = GadgetHooks::getDefinitionTitleFromID( $gadget->getId() ); |
| | 331 | + $exportTitles[] = GadgetsHooks::getDefinitionTitleFromID( $gadget->getId() ); |
| 332 | 332 | |
| 333 | 333 | // Title message in NS_MEDIAWIKI |
| 334 | 334 | $exportTitles[] = Title::makeTitleSafe( NS_MEDIAWIKI, $gadget->getTitleMessageKey() ); |
| Index: branches/RL2/extensions/Gadgets/Gadgets.hooks.php |
| — | — | @@ -0,0 +1,431 @@ |
| | 2 | +<?php |
| | 3 | +/** |
| | 4 | + * Gadgets extension - lets users select custom javascript gadgets |
| | 5 | + * |
| | 6 | + * |
| | 7 | + * For more info see http://mediawiki.org/wiki/Extension:Gadgets |
| | 8 | + * |
| | 9 | + * @file |
| | 10 | + * @ingroup Extensions |
| | 11 | + * @author Daniel Kinzler, brightbyte.de |
| | 12 | + * @copyright © 2007 Daniel Kinzler |
| | 13 | + * @license GNU General Public Licence 2.0 or later |
| | 14 | + */ |
| | 15 | + |
| | 16 | +class GadgetsHooks { |
| | 17 | + /** |
| | 18 | + * Get the gadget ID from a title |
| | 19 | + * @param $title Title object |
| | 20 | + * @return string Gadget id or null if not a gadget definition page |
| | 21 | + */ |
| | 22 | + public static function getIDFromTitle( Title $title ) { |
| | 23 | + $id = $title->getText(); |
| | 24 | + if ( $title->getNamespace() !== NS_GADGET_DEFINITION || !preg_match( '!\.js$!u', $id ) ) { |
| | 25 | + // Not a gadget definition page |
| | 26 | + return null; |
| | 27 | + } |
| | 28 | + // Trim .js from the page name to obtain the gadget ID |
| | 29 | + return substr( $id, 0, -3 ); |
| | 30 | + } |
| | 31 | + |
| | 32 | + /** |
| | 33 | + * Get a Title object of the gadget definition page from a gadget id |
| | 34 | + * @param $is String |
| | 35 | + * @return Title|null |
| | 36 | + */ |
| | 37 | + public static function getDefinitionTitleFromID( $id ) { |
| | 38 | + return Title::makeTitleSafe( NS_GADGET_DEFINITION, $id . '.js' ); |
| | 39 | + } |
| | 40 | + |
| | 41 | + /** |
| | 42 | + * ArticleDeleteComplete hook handler. |
| | 43 | + * |
| | 44 | + * @param $article Article |
| | 45 | + * @param $user User |
| | 46 | + * @param $reason String: Deletion summary |
| | 47 | + * @param $id Int: Page ID |
| | 48 | + */ |
| | 49 | + public static function gadgetDefinitionDelete( $article, $user, $reason, $id ) { |
| | 50 | + $id = self::getIDFromTitle( $article->getTitle() ); |
| | 51 | + if ( !$id ) { |
| | 52 | + return true; |
| | 53 | + } |
| | 54 | + |
| | 55 | + $repo = LocalGadgetRepo::singleton(); |
| | 56 | + $repo->deleteGadget( $id ); |
| | 57 | + // deleteGadget() may return an error if the Gadget didn't exist, but we don't care here |
| | 58 | + return true; |
| | 59 | + } |
| | 60 | + |
| | 61 | + /** |
| | 62 | + * ArticleSaveComplete hook handler. |
| | 63 | + * |
| | 64 | + * @param $article Article |
| | 65 | + * @param $user User |
| | 66 | + * @param $text String: New page text |
| | 67 | + * @param $summary String: Edit summary |
| | 68 | + * @param $isMinor Bool: Whether this was a minor edit |
| | 69 | + * @param $isWatch unused |
| | 70 | + * @param $section unused |
| | 71 | + * @param $flags: Int: Bitmap of flags passed to WikiPage::doEdit() |
| | 72 | + * @param $revision: Revision object for the new revision |
| | 73 | + */ |
| | 74 | + public static function gadgetDefinitionSave( $article, $user, $text, $summary, $isMinor, |
| | 75 | + $isWatch, $section, $flags, $revision ) |
| | 76 | + { |
| | 77 | + $id = self::getIDFromTitle( $article->getTitle() ); |
| | 78 | + if ( !$id ) { |
| | 79 | + return true; |
| | 80 | + } |
| | 81 | + |
| | 82 | + $previousRev = $revision->getPrevious(); |
| | 83 | + $prevTs = $previousRev instanceof Revision ? $previousRev->getTimestamp() : wfTimestampNow(); |
| | 84 | + |
| | 85 | + // Update the database entry for this gadget |
| | 86 | + $repo = LocalGadgetRepo::singleton(); |
| | 87 | + // TODO: Timestamp in the constructor is ugly |
| | 88 | + $gadget = new Gadget( $id, $repo, $text, $prevTs ); |
| | 89 | + $repo->modifyGadget( $gadget, $revision->getTimestamp() ); |
| | 90 | + |
| | 91 | + // modifyGadget() returns a Status object with an error if there was a conflict, |
| | 92 | + // but we don't care. If a conflict occurred, that must be because a newer edit's |
| | 93 | + // DB update occurred before ours, in which case the right thing to do is to occu |
| | 94 | + |
| | 95 | + return true; |
| | 96 | + } |
| | 97 | + |
| | 98 | + /** |
| | 99 | + * Update the database entry for a gadget if the description page is |
| | 100 | + * newer than the database entry. |
| | 101 | + * @param $title Title object |
| | 102 | + */ |
| | 103 | + public static function gadgetDefinitionUpdateIfChanged( $title ) { |
| | 104 | + $id = self::getIDFromTitle( $title ); |
| | 105 | + if ( !$id ) { |
| | 106 | + return; |
| | 107 | + } |
| | 108 | + |
| | 109 | + // Check whether this undeletion changed the latest revision of the page, by comparing |
| | 110 | + // the timestamp of the latest revision with the timestamp in the DB |
| | 111 | + $repo = LocalGadgetRepo::singleton(); |
| | 112 | + $gadget = $repo->getGadget( $id ); |
| | 113 | + $gadgetTS = $gadget ? $gadget->getTimestamp() : 0; |
| | 114 | + |
| | 115 | + $rev = Revision::newFromTitle( $title ); |
| | 116 | + if ( wfTimestamp( TS_MW, $rev->getTimestamp() ) === |
| | 117 | + wfTimestamp( TS_MW, $gadgetTS ) ) { |
| | 118 | + // The latest rev didn't change. Someone must've undeleted an older revision |
| | 119 | + return; |
| | 120 | + } |
| | 121 | + |
| | 122 | + // Update the database entry for this gadget |
| | 123 | + $newGadget = new Gadget( $id, $repo, $rev->getRawText(), $gadgetTS ); |
| | 124 | + $repo->modifyGadget( $newGadget, $rev->getTimestamp() ); |
| | 125 | + |
| | 126 | + // modifyGadget() returns a Status object with an error if there was a conflict, |
| | 127 | + // but we do't care, see similar comment in articleSaveComplete() |
| | 128 | + return; |
| | 129 | + } |
| | 130 | + |
| | 131 | + /** |
| | 132 | + * ArticleUndelete hook handler |
| | 133 | + * @param $title Title object |
| | 134 | + * @param $created Bool: Whether this undeletion recreated the page |
| | 135 | + * @param $comment String: Undeletion summary |
| | 136 | + */ |
| | 137 | + public static function gadgetDefinitionUndelete( $title, $created, $comment ) { |
| | 138 | + self::gadgetDefinitionUpdateIfChanged( $title ); |
| | 139 | + return true; |
| | 140 | + } |
| | 141 | + |
| | 142 | + public static function gadgetDefinitionImport( $title, $origTitle, $revCount, $sRevCount, $pageInfo ) { |
| | 143 | + self::gadgetDefinitionUpdateIfChanged( $title ); |
| | 144 | + return true; |
| | 145 | + } |
| | 146 | + |
| | 147 | + /** |
| | 148 | + * ArticleDeleteComplete hook handler. |
| | 149 | + * |
| | 150 | + * @param $article Article |
| | 151 | + * @param $user User |
| | 152 | + * @param $reason String: Deletion summary |
| | 153 | + * @param $id Int: Page ID |
| | 154 | + */ |
| | 155 | + public static function cssJsPageDelete( $article, $user, $reason, $id ) { |
| | 156 | + GadgetPageList::delete( $article->getTitle() ); |
| | 157 | + return true; |
| | 158 | + } |
| | 159 | + |
| | 160 | + /** |
| | 161 | + * ArticleSaveComplete hook handler. |
| | 162 | + * |
| | 163 | + * @param $article Article |
| | 164 | + * @param $user User |
| | 165 | + * @param $text String: New page text |
| | 166 | + * @param $summary String: Edit summary |
| | 167 | + * @param $isMinor Bool: Whether this was a minor edit |
| | 168 | + * @param $isWatch unused |
| | 169 | + * @param $section unused |
| | 170 | + * @param $flags: Int: Bitmap of flags passed to WikiPage::doEdit() |
| | 171 | + * @param $revision: Revision object for the new revision |
| | 172 | + */ |
| | 173 | + public static function cssOrJsPageSave( $article, $user, $text, $summary, $isMinor, |
| | 174 | + $isWatch, $section, $flags, $revision ) |
| | 175 | + { |
| | 176 | + $title = $article->getTitle(); |
| | 177 | + GadgetPageList::updatePageStatus( $title ); |
| | 178 | + return true; |
| | 179 | + } |
| | 180 | + |
| | 181 | + /** |
| | 182 | + * ArticleUndelete hook handler |
| | 183 | + * @param $title Title object |
| | 184 | + * @param $created Bool: Whether this undeletion recreated the page |
| | 185 | + * @param $comment String: Undeletion summary |
| | 186 | + */ |
| | 187 | + public static function cssOrJsPageUndelete( $title, $created, $comment ) { |
| | 188 | + GadgetPageList::updatePageStatus( $title ); |
| | 189 | + return true; |
| | 190 | + } |
| | 191 | + |
| | 192 | + public static function cssOrJsPageMove( $oldTitle, $newTitle, $user, $pageid, $redirid ) { |
| | 193 | + // Delete the old title from the list. Even if it still exists after the move, |
| | 194 | + // it'll be a redirect and we don't want those in there |
| | 195 | + GadgetPageList::delete( $oldTitle ); |
| | 196 | + |
| | 197 | + GadgetPageList::updatePageStatus( $newTitle ); |
| | 198 | + return true; |
| | 199 | + } |
| | 200 | + |
| | 201 | + /** |
| | 202 | + * UserGetDefaultOptions hook handler |
| | 203 | + * @param $defaultOptions Array of default preference keys and values |
| | 204 | + */ |
| | 205 | + public static function userGetDefaultOptions( &$defaultOptions ) { |
| | 206 | + $repo = LocalGadgetRepo::singleton(); |
| | 207 | + $gadgetIds = $repo->getGadgetIds(); |
| | 208 | + foreach ( $gadgetIds as $gadgetId ) { |
| | 209 | + $gadget = $repo->getGadget( $gadgetId ); |
| | 210 | + if ( $gadget->isEnabledByDefault() ) { |
| | 211 | + $defaultOptions['gadget-' . $gadget->getId()] = 1; |
| | 212 | + } |
| | 213 | + } |
| | 214 | + return true; |
| | 215 | + } |
| | 216 | + |
| | 217 | + /** |
| | 218 | + * GetPreferences hook handler. |
| | 219 | + * @param $user User |
| | 220 | + * @param $preferences Array: Preference descriptions |
| | 221 | + */ |
| | 222 | + public static function getPreferences( $user, &$preferences ) { |
| | 223 | + $repo = LocalGadgetRepo::singleton(); |
| | 224 | + $gadgets = $repo->getGadgetIds(); |
| | 225 | + $categories = array(); // array( category => array( desc => title ) ) |
| | 226 | + $default = array(); // array of Gadget ids |
| | 227 | + foreach ( $gadgets as $id ) { |
| | 228 | + $gadget = $repo->getGadget( $id ); |
| | 229 | + if ( !$gadget->isAllowed( $user ) || $gadget->isHidden() ) { |
| | 230 | + continue; |
| | 231 | + } |
| | 232 | + $category = $gadget->getCategory(); |
| | 233 | + |
| | 234 | + // Add the Gadget to the right category |
| | 235 | + $title = htmlspecialchars( $gadget->getTitleMessage() ); |
| | 236 | + $description = $gadget->getDescriptionMessage(); // Is parsed, doesn't need escaping |
| | 237 | + if ( $description === '' ) { |
| | 238 | + // Empty description, just use the title |
| | 239 | + $text = $title; |
| | 240 | + } else { |
| | 241 | + $text = wfMessage( 'gadgets-preference-description' )->rawParams( $title, $description )->parse(); |
| | 242 | + } |
| | 243 | + $categories[$category][$text] = $id; |
| | 244 | + // Add the Gadget to the default list if enabled |
| | 245 | + if ( $gadget->isEnabledForUser( $user ) ) { |
| | 246 | + $default[] = $id; |
| | 247 | + } |
| | 248 | + } |
| | 249 | + |
| | 250 | + $options = array(); // array( desc1 => gadget1, category1 => array( desc2 => gadget2 ) ) |
| | 251 | + foreach ( $categories as $category => $gadgets ) { |
| | 252 | + if ( $category !== '' ) { |
| | 253 | + $categoryMsg = htmlspecialchars( $repo->getCategoryTitle( $category ) ); |
| | 254 | + $options[$categoryMsg] = $gadgets; |
| | 255 | + } else { |
| | 256 | + $options += $gadgets; |
| | 257 | + } |
| | 258 | + } |
| | 259 | + |
| | 260 | + $preferences['gadgets-intro'] = |
| | 261 | + array( |
| | 262 | + 'type' => 'info', |
| | 263 | + 'label' => ' ', |
| | 264 | + 'default' => Xml::tags( 'tr', array(), |
| | 265 | + Xml::tags( 'td', array( 'colspan' => 2 ), |
| | 266 | + wfMsgExt( 'gadgets-prefstext', 'parse' ) ) ), |
| | 267 | + 'section' => 'gadgets', |
| | 268 | + 'raw' => 1, |
| | 269 | + 'rawrow' => 1, |
| | 270 | + ); |
| | 271 | + $preferences['gadgets'] = |
| | 272 | + array( |
| | 273 | + 'type' => 'multiselect', |
| | 274 | + 'options' => $options, |
| | 275 | + 'section' => 'gadgets', |
| | 276 | + 'label' => ' ', |
| | 277 | + 'prefix' => 'gadget-', |
| | 278 | + 'default' => $default, |
| | 279 | + ); |
| | 280 | + |
| | 281 | + // Add tab for shared gadgets |
| | 282 | + $preferences['gadgets-intro-shared'] = |
| | 283 | + array( |
| | 284 | + 'type' => 'info', |
| | 285 | + 'label' => ' ', |
| | 286 | + 'default' => Xml::tags( 'tr', array(), |
| | 287 | + Xml::tags( 'td', array( 'colspan' => 2 ), |
| | 288 | + wfMsgExt( 'gadgets-sharedprefstext', 'parse' ) ) ), |
| | 289 | + 'section' => 'gadgets-shared', |
| | 290 | + 'raw' => 1, |
| | 291 | + 'rawrow' => 1, |
| | 292 | + ); |
| | 293 | + $preferences['gadgets-shared'] = |
| | 294 | + array( |
| | 295 | + 'type' => 'multiselect', |
| | 296 | + 'options' => array(), // TODO: Maybe fill in stuff anyway? The backend may need that |
| | 297 | + 'section' => 'gadgets-shared', |
| | 298 | + 'label' => ' ', |
| | 299 | + 'prefix' => 'gadget-', |
| | 300 | + 'default' => array(), |
| | 301 | + ); |
| | 302 | + return true; |
| | 303 | + } |
| | 304 | + |
| | 305 | + /** |
| | 306 | + * ResourceLoaderRegisterModules hook handler. |
| | 307 | + * @param $resourceLoader ResourceLoader |
| | 308 | + */ |
| | 309 | + public static function registerModules( &$resourceLoader ) { |
| | 310 | + $gadgets = GadgetRepo::getAllGadgets(); |
| | 311 | + foreach ( $gadgets as $gadget ) { |
| | 312 | + $resourceLoader->register( $gadget->getModuleName(), $gadget->getModule() ); |
| | 313 | + } |
| | 314 | + return true; |
| | 315 | + } |
| | 316 | + |
| | 317 | + /** |
| | 318 | + * BeforePageDisplay hook handler. |
| | 319 | + * @param $out OutputPage |
| | 320 | + */ |
| | 321 | + public static function beforePageDisplay( $out ) { |
| | 322 | + wfProfileIn( __METHOD__ ); |
| | 323 | + |
| | 324 | + $user = $out->getUser(); |
| | 325 | + $gadgets = GadgetRepo::getAllGadgets(); |
| | 326 | + foreach ( $gadgets as $gadget ) { |
| | 327 | + if ( $gadget->isEnabledForUser( $user ) && $gadget->isAllowed( $user ) ) { |
| | 328 | + $out->addModules( $gadget->getModuleName() ); |
| | 329 | + } |
| | 330 | + } |
| | 331 | + |
| | 332 | + // Add preferences JS if we're on Special:Preferences |
| | 333 | + if ( $out->getTitle()->equals( SpecialPage::getTitleFor( 'Preferences' ) ) ) { |
| | 334 | + $out->addModules( 'ext.gadgets.preferences' ); |
| | 335 | + } |
| | 336 | + |
| | 337 | + wfProfileOut( __METHOD__ ); |
| | 338 | + return true; |
| | 339 | + } |
| | 340 | + |
| | 341 | + /** |
| | 342 | + * MakeGlobalVariablesScript hook handler |
| | 343 | + * @param $vars Array: Key/value pars for mw.config.set on this page. |
| | 344 | + * @param $out OutputPage |
| | 345 | + */ |
| | 346 | + public static function makeGlobalVariablesScript( &$vars, $out ) { |
| | 347 | + $title = $out->getTitle(); |
| | 348 | + $user = $out->getUser(); |
| | 349 | + // FIXME: This is not a nice way to do it. Maybe we should check for the presence |
| | 350 | + // of a module instead or something. |
| | 351 | + if ( $title->equals( SpecialPage::getTitleFor( 'Gadgets' ) ) || |
| | 352 | + $title->equals( SpecialPage::getTitleFor( 'Preferences' ) ) ) |
| | 353 | + { |
| | 354 | + global $wgGadgetEnableSharing; |
| | 355 | + |
| | 356 | + // Pass the source data for each source that is used by a repository |
| | 357 | + $repos = GadgetRepo::getAllRepos(); |
| | 358 | + $sources = $out->getResourceLoader()->getSources(); |
| | 359 | + $repoData = array(); |
| | 360 | + foreach ( $repos as $repo ) { |
| | 361 | + $repoData[$repo->getSource()] = $sources[$repo->getSource()]; |
| | 362 | + } |
| | 363 | + |
| | 364 | + $vars['gadgetsConf'] = array( |
| | 365 | + 'enableSharing' => $wgGadgetEnableSharing, |
| | 366 | + 'allRights' => User::getAllRights(), |
| | 367 | + 'repos' => $repoData, |
| | 368 | + 'userIsAllowed' => array( |
| | 369 | + 'editinterface' => $user->isAllowed( 'editinterface' ), |
| | 370 | + 'gadgets-definition-create' => $user->isAllowed( 'gadgets-definition-create' ), |
| | 371 | + 'gadgets-definition-edit' => $user->isAllowed( 'gadgets-definition-edit' ), |
| | 372 | + 'gadgets-definition-delete' => $user->isAllowed( 'gadgets-definition-delete' ), |
| | 373 | + ), |
| | 374 | + ); |
| | 375 | + } |
| | 376 | + return true; |
| | 377 | + } |
| | 378 | + |
| | 379 | + /** |
| | 380 | + * UnitTestsList hook handler |
| | 381 | + * @param $files Array: List of extension test files |
| | 382 | + */ |
| | 383 | + public static function unitTestsList( &$files ) { |
| | 384 | + $files[] = dirname( __FILE__ ) . '/tests/GadgetsTest.php'; |
| | 385 | + return true; |
| | 386 | + } |
| | 387 | + |
| | 388 | + public static function loadExtensionSchemaUpdates( $updater ) { |
| | 389 | + $dir = dirname( __FILE__ ); |
| | 390 | + $updater->addExtensionUpdate( array( 'addtable', 'gadgets', "$dir/sql/gadgets.sql", true ) ); |
| | 391 | + $updater->addExtensionUpdate( array( 'addtable', 'gadgetpagelist', "$dir/sql/patch-gadgetpagelist.sql", true ) ); |
| | 392 | + return true; |
| | 393 | + } |
| | 394 | + |
| | 395 | + public static function canonicalNamespaces( &$list ) { |
| | 396 | + $list[NS_GADGET] = 'Gadget'; |
| | 397 | + $list[NS_GADGET_TALK] = 'Gadget_talk'; |
| | 398 | + $list[NS_GADGET_DEFINITION] = 'Gadget_definition'; |
| | 399 | + $list[NS_GADGET_DEFINITION_TALK] = 'Gadget_definition_talk'; |
| | 400 | + return true; |
| | 401 | + } |
| | 402 | + |
| | 403 | + public static function titleIsCssOrJsPage( $title, &$result ) { |
| | 404 | + if ( ( $title->getNamespace() == NS_GADGET || $title->getNamespace() == NS_GADGET_DEFINITION ) && |
| | 405 | + preg_match( '!\.(css|js)$!u', $title->getText() ) ) |
| | 406 | + { |
| | 407 | + $result = true; |
| | 408 | + } |
| | 409 | + return true; |
| | 410 | + } |
| | 411 | + |
| | 412 | + public static function titleIsMovable( $title, &$result ) { |
| | 413 | + if ( $title->getNamespace() == NS_GADGET_DEFINITION ) { |
| | 414 | + $result = false; |
| | 415 | + } |
| | 416 | + return true; |
| | 417 | + } |
| | 418 | + |
| | 419 | + public static function getUserPermissionsErrors( $title, $user, $action, &$result ) { |
| | 420 | + if ( $title->getNamespace() == NS_GADGET_DEFINITION ) { |
| | 421 | + // Enforce restrictions on the Gadget_definition namespace |
| | 422 | + if ( $action == 'create' && !$user->isAllowed( 'gadgets-definition-create' ) ) { |
| | 423 | + $result[] = array( 'gadgets-cant-create' ); |
| | 424 | + return false; |
| | 425 | + } elseif ( $action == 'delete' && !$user->isAllowed( 'gadgets-definition-delete' ) ) { |
| | 426 | + $result[] = array( 'gadgets-cant-delete' ); |
| | 427 | + return false; |
| | 428 | + } |
| | 429 | + } |
| | 430 | + return true; |
| | 431 | + } |
| | 432 | +} |
| Property changes on: branches/RL2/extensions/Gadgets/Gadgets.hooks.php |
| ___________________________________________________________________ |
| Added: svn:mergeinfo |
| 1 | 433 | Merged /branches/Gadgets-work/Gadgets_body.php:r73145-76526 |
| 2 | 434 | Merged /branches/wmf/1.17wmf1/extensions/Gadgets/Gadgets_body.php:r81884 |
| Added: svn:eol-style |
| 3 | 435 | + native |
| Added: svn:keywords |
| 4 | 436 | + LastChangedDate LastChangedRevision |