Page MenuHomePhabricator

Clarify how 'default' option should be used for preferences
Open, MediumPublic

Description

[[mw:Manual:Hooks/GetPreferences#Example]] suggests the 'default' form option is allowed (suggested, even) for preferences. Looking at Preferences::getPreferences() though, it seems that any default defined that way will override defaults coming from the database and thus cause the preferences form to display wrong data.

Steps to reproduce:

  • in the GetPreferences hook add a preference with type=toggle, default=true
  • log in as some user, set that preference to false, save

The preference will be correctly set to false but the form will continue to display true (checked checkbox).

The relevant code snippet from Preferences::getPreferences() ($info will be whatever was set by the hook):

// If it validates, set it as the default
if ( isset( $info['default'] ) ) {
	// Already set, no problem
	continue;
} elseif ( !is_null( $prefFromUser ) && // Make sure we're not just pulling nothing
		$field->validate( $prefFromUser, $user->getOptions() ) === true ) {
	$info['default'] = $prefFromUser;
} elseif ( $field->validate( $globalDefault, $user->getOptions() ) === true ) {
	$info['default'] = $globalDefault;
} else {
	throw new MWException( "Global default '$globalDefault' is invalid for field $name" );
}

Not sure if this is a bug or a documentation issue, although I can't really imagine a use-case where overriding the user's actual preference setting with a hardcoded default would make sense, so overriding the default with user or global pref makes more sense. (Maybe the actual issue is that the 'default' field returned by getPreferences() is used to set the default input state in the preferences form, but has different semantics in other places?)


Version: 1.23.0
Severity: normal

Details

Reference
bz63033