| Index: branches/RL2/extensions/Gadgets/Gadgets.php |
| — | — | @@ -108,6 +108,7 @@ |
| 109 | 109 | $wgHooks['GetPreferences'][] = 'GadgetsHooks::getPreferences'; |
| 110 | 110 | $wgHooks['UserGetDefaultOptions'][] = 'GadgetsHooks::userGetDefaultOptions'; |
| 111 | 111 | $wgHooks['LoadExtensionSchemaUpdates'][] = 'GadgetsHooks::loadExtensionSchemaUpdates'; |
| | 112 | +$wgHooks['PreferencesGetLegend'][] = 'GadgetsHooks::preferencesGetLegend'; |
| 112 | 113 | $wgHooks['ResourceLoaderRegisterModules'][] = 'GadgetsHooks::registerModules'; |
| 113 | 114 | $wgHooks['TitleIsCssOrJsPage'][] = 'GadgetsHooks::titleIsCssOrJsPage'; |
| 114 | 115 | $wgHooks['TitleIsMovable'][] = 'GadgetsHooks::titleIsMovable'; |
| Index: branches/RL2/extensions/Gadgets/Gadgets.hooks.php |
| — | — | @@ -224,43 +224,7 @@ |
| 225 | 225 | * @param $preferences Array: Preference descriptions |
| 226 | 226 | */ |
| 227 | 227 | public static function getPreferences( $user, &$preferences ) { |
| 228 | | - $repo = LocalGadgetRepo::singleton(); |
| 229 | | - $gadgets = $repo->getGadgetIds(); |
| 230 | | - $categories = array(); // array( category => array( desc => title ) ) |
| 231 | | - $default = array(); // array of Gadget ids |
| 232 | | - foreach ( $gadgets as $id ) { |
| 233 | | - $gadget = $repo->getGadget( $id ); |
| 234 | | - if ( !$gadget->isAllowed( $user ) || $gadget->isHidden() ) { |
| 235 | | - continue; |
| 236 | | - } |
| 237 | | - $category = $gadget->getCategory(); |
| 238 | | - |
| 239 | | - // Add the Gadget to the right category |
| 240 | | - $title = htmlspecialchars( $gadget->getTitleMessage() ); |
| 241 | | - $description = $gadget->getDescriptionMessage(); // Is parsed, doesn't need escaping |
| 242 | | - if ( $description === '' ) { |
| 243 | | - // Empty description, just use the title |
| 244 | | - $text = $title; |
| 245 | | - } else { |
| 246 | | - $text = wfMessage( 'gadgets-preference-description' )->rawParams( $title, $description )->parse(); |
| 247 | | - } |
| 248 | | - $categories[$category][$text] = $id; |
| 249 | | - // Add the Gadget to the default list if enabled |
| 250 | | - if ( $gadget->isEnabledForUser( $user ) ) { |
| 251 | | - $default[] = $id; |
| 252 | | - } |
| 253 | | - } |
| 254 | | - |
| 255 | | - $options = array(); // array( desc1 => gadget1, category1 => array( desc2 => gadget2 ) ) |
| 256 | | - foreach ( $categories as $category => $gadgets ) { |
| 257 | | - if ( $category !== '' ) { |
| 258 | | - $categoryMsg = htmlspecialchars( $repo->getCategoryTitle( $category ) ); |
| 259 | | - $options[$categoryMsg] = $gadgets; |
| 260 | | - } else { |
| 261 | | - $options += $gadgets; |
| 262 | | - } |
| 263 | | - } |
| 264 | | - |
| | 228 | + // Add tab for local gadgets |
| 265 | 229 | $preferences['gadgets-intro'] = |
| 266 | 230 | array( |
| 267 | 231 | 'type' => 'info', |
| — | — | @@ -272,15 +236,6 @@ |
| 273 | 237 | 'raw' => 1, |
| 274 | 238 | 'rawrow' => 1, |
| 275 | 239 | ); |
| 276 | | - $preferences['gadgets'] = |
| 277 | | - array( |
| 278 | | - 'type' => 'multiselect', |
| 279 | | - 'options' => $options, |
| 280 | | - 'section' => 'gadgets', |
| 281 | | - 'label' => ' ', |
| 282 | | - 'prefix' => 'gadget-', |
| 283 | | - 'default' => $default, |
| 284 | | - ); |
| 285 | 240 | |
| 286 | 241 | // Add tab for shared gadgets |
| 287 | 242 | $preferences['gadgets-intro-shared'] = |
| — | — | @@ -295,26 +250,58 @@ |
| 296 | 251 | 'rawrow' => 1, |
| 297 | 252 | ); |
| 298 | 253 | |
| 299 | | - // Build an array with all the shared gadget preferences with dummy descriptions. |
| 300 | | - // These descriptions will be completed by JavaScript |
| 301 | | - $remoteGadgets = GadgetRepo::getAllRemoteGadgetIDs(); |
| 302 | | - $sharedOptions = array(); |
| 303 | | - foreach ( $remoteGadgets as $id ) { |
| 304 | | - // Use the gadget name as a dummy description |
| 305 | | - $sharedOptions[$id] = $id; |
| | 254 | + // This loop adds the preferences for all gadgets, both local and remote |
| | 255 | + $repos = GadgetRepo::getAllRepos(); |
| | 256 | + foreach ( $repos as $repo ) { |
| | 257 | + $repoSource = $repo->getSource(); |
| | 258 | + $byCategory = $repo->getGadgetsByCategory(); |
| | 259 | + ksort( $byCategory ); |
| | 260 | + foreach ( $byCategory as $category => $gadgets ) { |
| | 261 | + foreach ( $gadgets as $gadget ) { |
| | 262 | + $id = $gadget->getId(); |
| | 263 | + $sectionCat = $category === '' ? '' : "/gadgetcategory-$category"; |
| | 264 | + if ( $repo->isLocal() ) { |
| | 265 | + // For local gadgets we have all the information |
| | 266 | + $title = htmlspecialchars( $gadget->getTitleMessage() ); |
| | 267 | + $description = $gadget->getDescriptionMessage(); // Is parsed, doesn't need escaping |
| | 268 | + if ( $description === '' ) { |
| | 269 | + // Empty description, just use the title |
| | 270 | + $text = $title; |
| | 271 | + } else { |
| | 272 | + $text = wfMessage( 'gadgets-preference-description' )->rawParams( $title, $description )->parse(); |
| | 273 | + } |
| | 274 | + $preferences["gadget-$id"] = array( |
| | 275 | + 'type' => 'toggle', |
| | 276 | + 'label' => $text, |
| | 277 | + 'section' => "gadgets$sectionCat", |
| | 278 | + 'default' => $gadget->isEnabledForUser( $user ), |
| | 279 | + ); |
| | 280 | + } else { |
| | 281 | + $preferences["gadget-$id"] = array( |
| | 282 | + 'type' => 'toggle', |
| | 283 | + 'label' => htmlspecialchars( $id ), // will be changed by JS |
| | 284 | + // TODO the below means source and category IDs can't contain slashes, enforce this |
| | 285 | + 'section' => "gadgetsshared/gadgetrepo-$repoSource$sectionCat", |
| | 286 | + 'cssclass' => 'mw-gadgets-shared-pref', |
| | 287 | + //'default' => $gadget->isEnabledForUser( $user ), // TODO: should we honor 'default' for remote gadgets? |
| | 288 | + ); |
| | 289 | + } |
| | 290 | + } |
| | 291 | + } |
| 306 | 292 | } |
| 307 | | - $preferences['gadgetsshared'] = |
| 308 | | - array( |
| 309 | | - 'type' => 'multiselect', |
| 310 | | - 'options' => $sharedOptions, |
| 311 | | - 'section' => 'gadgetsshared', |
| 312 | | - 'label' => ' ', |
| 313 | | - 'prefix' => 'gadget-', |
| 314 | | - //'default' => array(), // TODO: should we honor 'default':true remotely or not? |
| 315 | | - 'cssclass' => 'mw-gadgetsshared-item-unloaded', |
| 316 | | - ); |
| | 293 | + |
| 317 | 294 | return true; |
| 318 | 295 | } |
| | 296 | + |
| | 297 | + public static function preferencesGetLegend( $form, $key, &$legend ) { |
| | 298 | + $matches = null; |
| | 299 | + if ( preg_match( '/^(gadgetcategory|gadgetrepo)-(.*)$/', $key, $matches ) ) { |
| | 300 | + // Just display the ID itself (with ucfirst applied) |
| | 301 | + // This will be changed to a properly i18ned string by JS |
| | 302 | + $legend = $form->getLang()->ucfirst( $matches[2] ); |
| | 303 | + } |
| | 304 | + return true; |
| | 305 | + } |
| 319 | 306 | |
| 320 | 307 | /** |
| 321 | 308 | * ResourceLoaderRegisterModules hook handler. |
| Index: branches/RL2/extensions/Gadgets/modules/ext.gadgets.preferences.js |
| — | — | @@ -6,47 +6,23 @@ |
| 7 | 7 | * @license GNU General Public Licence 2.0 or later |
| 8 | 8 | */ |
| 9 | 9 | ( function( $ ) { |
| 10 | | - /** |
| 11 | | - * Fixes the description and the categorization for shared gadgets in the preferences form. |
| 12 | | - * This hides the container td for shared gadgets preferences, reorders them by moving them |
| 13 | | - * into a new td in the right order, updates their label texts, then replaces the old td with |
| 14 | | - * the new one. |
| 15 | | - * @param gadgetsByCategory {Object} Map of { repo: { categoryID: { gadgetID: gadgetObj } } } |
| 16 | | - * @param categoryNames {Object} Map of { repo: { categoryID: categoryDescription } } |
| 17 | | - */ |
| 18 | 10 | function fixPreferenceForm( gadgetsByCategory, categoryNames ) { |
| 19 | | - // TODO i18n the repo names somehow |
| 20 | | - // TODO h1 and h2 need better styling |
| 21 | | - var $oldContainer = $( '#mw-prefsection-gadgetsshared' ).find( '.mw-input' ), |
| 22 | | - $newContainer = $( '<td>' ).addClass( 'mw-input' ), |
| 23 | | - $spinner = $oldContainer.closest( '.mw-gadgetsshared-item-unloaded' ), |
| 24 | | - repo, category, gadget, $oldItem; |
| 25 | 11 | for ( repo in gadgetsByCategory ) { |
| 26 | | - if ( repo == 'local' ) { |
| 27 | | - // Skip local repository |
| 28 | | - // FIXME: Just don't request the info in the first place then, waste of API reqs |
| 29 | | - continue; |
| 30 | | - } |
| 31 | | - $newContainer.append( $( '<h1>' ).text( repo ) ); |
| 32 | 12 | for ( category in gadgetsByCategory[repo] ) { |
| 33 | | - if ( category !== '' ) { |
| 34 | | - $newContainer.append( $( '<h2>' ).text( categoryNames[repo][category] ) ); |
| 35 | | - } |
| | 13 | + // FIXME HTMLForm isn't namespacing these things, we have to make it do that |
| | 14 | + // to prevent category naming collisions between repos |
| | 15 | + $( document.getElementById( 'mw-htmlform-gadgetcategory-' + category ) ) |
| | 16 | + .siblings( 'legend' ) |
| | 17 | + .text( categoryNames[repo][category] ); |
| | 18 | + |
| 36 | 19 | for ( gadget in gadgetsByCategory[repo][category] ) { |
| 37 | | - // Find the item belonging to this gadget in $oldContainer |
| 38 | | - $oldItem = $oldContainer |
| 39 | | - .find( '#mw-input-wpgadgetsshared-' + gadget ) |
| 40 | | - .closest( '.mw-htmlform-multiselect-item' ); |
| 41 | | - // Update the label text |
| 42 | | - $oldItem.find( 'label' ).text( gadgetsByCategory[repo][category][gadget].title ); |
| 43 | | - // Move the item from $oldContainer to $newContainer |
| 44 | | - $newContainer.append( $oldItem ); |
| | 20 | + // Use getElementById() because we'd have to escape gadget for selector stuff otherwise |
| | 21 | + $( document.getElementById( 'mw-input-wpgadget-' + gadget ) ) |
| | 22 | + .siblings( 'label' ) |
| | 23 | + .text( gadgetsByCategory[repo][category][gadget].title ); |
| 45 | 24 | } |
| 46 | 25 | } |
| 47 | 26 | } |
| 48 | | - $oldContainer.replaceWith( $newContainer ); |
| 49 | | - // Unhide the container by removing the unloaded class, and remove the spinner too |
| 50 | | - $spinner.removeClass( 'mw-gadgetsshared-item-unloaded mw-ajax-loader' ); |
| 51 | 27 | } |
| 52 | 28 | |
| 53 | 29 | /** |