r101364 MediaWiki - Code Review archive

Repository:MediaWiki
Revision:r101363‎ | r101364 | r101365 >
Date:16:45, 31 October 2011
Author:catrope
Status:deferred
Tags:
Comment:
[RL2] Use fieldsets instead of divs and h1's for sectioning the gadget preferences. Complete rewrite of getPreferences() and fixPreferenceForm(). This depends on some of today's core changes, including the PreferencesGetLegend hook.
Modified paths:
  • /branches/RL2/extensions/Gadgets/Gadgets.hooks.php (modified) (history)
  • /branches/RL2/extensions/Gadgets/Gadgets.php (modified) (history)
  • /branches/RL2/extensions/Gadgets/modules/ext.gadgets.preferences.js (modified) (history)

Diff [purge]

Index: branches/RL2/extensions/Gadgets/Gadgets.php
@@ -108,6 +108,7 @@
109109 $wgHooks['GetPreferences'][] = 'GadgetsHooks::getPreferences';
110110 $wgHooks['UserGetDefaultOptions'][] = 'GadgetsHooks::userGetDefaultOptions';
111111 $wgHooks['LoadExtensionSchemaUpdates'][] = 'GadgetsHooks::loadExtensionSchemaUpdates';
 112+$wgHooks['PreferencesGetLegend'][] = 'GadgetsHooks::preferencesGetLegend';
112113 $wgHooks['ResourceLoaderRegisterModules'][] = 'GadgetsHooks::registerModules';
113114 $wgHooks['TitleIsCssOrJsPage'][] = 'GadgetsHooks::titleIsCssOrJsPage';
114115 $wgHooks['TitleIsMovable'][] = 'GadgetsHooks::titleIsMovable';
Index: branches/RL2/extensions/Gadgets/Gadgets.hooks.php
@@ -224,43 +224,7 @@
225225 * @param $preferences Array: Preference descriptions
226226 */
227227 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
265229 $preferences['gadgets-intro'] =
266230 array(
267231 'type' => 'info',
@@ -272,15 +236,6 @@
273237 'raw' => 1,
274238 'rawrow' => 1,
275239 );
276 - $preferences['gadgets'] =
277 - array(
278 - 'type' => 'multiselect',
279 - 'options' => $options,
280 - 'section' => 'gadgets',
281 - 'label' => ' ',
282 - 'prefix' => 'gadget-',
283 - 'default' => $default,
284 - );
285240
286241 // Add tab for shared gadgets
287242 $preferences['gadgets-intro-shared'] =
@@ -295,26 +250,58 @@
296251 'rawrow' => 1,
297252 );
298253
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+ }
306292 }
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+
317294 return true;
318295 }
 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+ }
319306
320307 /**
321308 * ResourceLoaderRegisterModules hook handler.
Index: branches/RL2/extensions/Gadgets/modules/ext.gadgets.preferences.js
@@ -6,47 +6,23 @@
77 * @license GNU General Public Licence 2.0 or later
88 */
99 ( 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 - */
1810 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;
2511 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 ) );
3212 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+
3619 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 );
4524 }
4625 }
4726 }
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' );
5127 }
5228
5329 /**

Follow-up revisions

RevisionCommit summaryAuthorDate
r101367[RL2] Fixes for r101364...catrope17:08, 31 October 2011
r102858[RL2] Fix regression in r101364: fieldset legends for local categories will n...catrope11:39, 12 November 2011

Status & tagging log