I was just playing with a preferences experiment while running into this bug. It appears the way User->getOption works as of 1.18+, boolean preferences that are on by default cannot be set to false.
A good example can be found on translatewiki.net. Go to Special:Preferences#mw-prefsection-gadgets and look at the "No-op" gadget. If you uncheck that checkbox and save the preferences (which results in a success-msg "Your preferences have been saved."), then go back to the Gadgets tab and you'll find yourself seeing the checkbox still being checked.
Although I haven't been able to fix it, I believe the problem is caused by the code for '$defaultOverride' in User::getOption.
It is used in the preferences like this:
$default = FooBar::hasAwesomeness(); // e.g. true or false
$user->getOption( 'foobar', $default );
Inside User::getOption is code that looks very broken to me, no idea how this got passed code review (assuming it already has). See http://svn.wikimedia.org/viewvc/mediawiki/trunk/phase3/includes/User.php?revision=96442&view=markup&pathrev=96442#l2130
English verbalization of that function as of right now:
- CODE: If User::mOptions is null
- NOTE: OK. mOptions is a lazy-load cache for all options, not just this one
- call getDefaultOptions() and store it in User::mOptions
- NOTE: OK. We're lazy loading the options
- CODE: If $default is not an empty string
- CODE: Return $default
- NOTE: This makes no friggin sense at all. For one, this is inside the cache null check which is pretty much unrelated to this. Secondly, why is $default being checked for empty string ? This arguments defaults to false and moreover implies (without documentation) that a default may not be an empty string.
As a result the preferences panel is fairly broken. Some of the default preferences cannot be changed, and several other weird things happen (ie. when options are cached defaults are handled differently than when they're not cached..)