XWiki#getUserPreference() usage

Hi devs,

I’m looking at XWiki#getUserPreference() and I’m not sure I really understand how it’s meant to be used.

The issue I see is that it’ll start looking for the asked preference in the current user profile, in the XWiki.XWikiUsers xobject. And if not found it’ll look for that preference in the current space’s WebPreferences document (in a XWikiPreferences xobject), and then in the wiki’s XWikiPreferences document (in a XWikiPreferences xobject).

So the xobject in which we look for are from different xclasses so it seems weird we’re looking for a given preference xproperty in different xclasses. It would mean that XWiki users would need to modify their XWikiPreferences xclass in their wiki to add the xproperty, which seems a bit weird.

If we were looking for a XWiki.XWikiUsers xobject in the current space’s WebPreferences document or in the current wiki’s XWikiPreferences document , then it would make more sense to me.

What could also make sense would be the opposite (but then the getUserPreference() name is not good), would be to look for the property in a user profile’s XWiki.XWikiPreferences xobject.

So do you agree that the current situation is weird and doesn’t make much sense?

FYI, ATM we use XWiki#getUserPreference() in 21 places right now in platform.

Example 1 (using a preference belonging to a user):

## Build and run the Solr query.
#set ($suggestionsQuery = $services.query.createQuery($suggestionsQueryString, "solr"))
#set ($filterQuery = ['type:"DOCUMENT"', "locale:(""$xcontext.locale"" OR """")"])
#if ($xwiki.getUserPreference('displayHiddenDocuments') != 1)
  #set ($discard = $filterQuery.add('hidden:false'))
#end

Example 2 (using a preference belonging to a XWikiPreferences):

    #set($leftPanels = $xwiki.getUserPreference("leftPanels"))
    #if($leftPanels == "")
       #set($leftPanels = $xwiki.getSpacePreference("leftPanels"))
    #end

(side note: the fallback here is not needed since it’s done by default in getUserPreference())

WDYT?

FTR I’ve found this usage today but it looks like “pure luck” that we have the same xproperty name for both XClasses:

    ## Use the preferred content editor.
    #set ($useWysiwygEditor = $xwiki.getUserPreference('editor') == 'Wysiwyg')

(ie that “editor” exists in both XWikiUsers and XWikiPreferences).

It’s clearly not the case for 95% of the other xproperties from both XClasses.

I don’t think it’s luck, seems to me it was just designed that way. It’s actually the opposite: which class is used to store the preferences is an implementation detail in this case.

The problem is using two different XClasses and that doesn’t make any sense to me. There’ll always be a mismatch. It would make more sense if an XWikiUsers xclass was put in XWikiPreferences to provide default user configuration details when not specified by users for example.

Or the other way around, that User profile pages could hold a XWikiPreferences xobject to override wiki config values.

But from the name of the API (getUserPreference()), it should be about user preferences so the first option I was mentioning, ie. " It would make more sense if an XWikiUsers xclass was put in XWikiPreferences to provide default user configuration details when not specified by users for example.".

I’m asking these questions as I’m trying to think about a more modern API for this use case. We now have the new User API. I’d use a “user” ConfigurationSource that looks in a “space” and “wiki” ConfigurationSource (and even till the “xwikiproperties” one), if not defined at the level of the “user”.

It seems to me that it already exists and that it’s the AllConfigurationSource (“all” CS).

WDYT?

Only problem is in offering a typed API too.

But that’s not too hard actually :slight_smile:

Right now the User API uses the “user” CS. We could make it use the “all” CS and that should be enough to provide the typed API.

I just need to remember how we do the mapping between xwikiproperties keys and wiki keys :wink: (I think we don’t and that would need some work to make it nicer).

It’s the same as saying that it does not make sense to fallback on xwiki.properties which is the case for the default CS.

It’s not really the same because xwiki.properties is untyped whereas XClasses are. So you can’t use it without changing the structure of the XClass. But yes I get your point and it’s ok for now if we’re ok to stop using getUserPreference and instead use CS (we’ll need a way to access them from scripts too).

Big -1 to that since there is plenty of stuff a user should not be able to override from the preferences.

Yes that would make sense and also make easier reuse the user profile displayer to configure default user preferences but we would probably still need to try the XWikiPreference (what is done now) class for retro compatibility reasons.

My bad, we should use the new User API :slight_smile: (and use the “all” CS internally behind the user API)