User Panels - A Proposal

User Panels shoots pretty high: it aims to provide a consistent, easy platform for the handling of user-centric information display. It's not about new storage mechanisms or anything like that - just about marshaling all that user content together in a sane, easy-to-use way. I'm hoping that this blog post can be a semi-official shout-out to the drupal community - an RFC, I guess.

user_panels comes out of a basic observation about Drupal: virtually every Drupal site has a different conceptualization of who users are, what their role is within the site, how they should be interacting with one another, etc. This observation helps explain why it's been so difficult to settle the question of how 'users' ought to be handled - most folks, myself absolutely included, are coming from the perspective of a particular use case. Even with deliberate effort, it's been pretty tough to get into a genericized head-space with respect to users. There are, I think, a couple reasons for this.

IMPORTANT NOTE: much of this probably sounds like a proposal for core. It's not. While I'd personally like to see a solution along these lines integrated into core, this solution requires Panels, which would mean getting the Panels engine into core - and that's a whole other bag of chips. This idea CAN be implemented entirely in contrib, and that's what my focus is on here.

The 'User-Centric' Challenge

The first problem is tied to data storage: almost all of the profile solutions that have arisen store user data in nodes. Specifically, there's bio and nodeprofile for D5, which have merged (and an enormous kudos to everyone involved in that effort!) into content profile for D6. Now, many debates have been had about the appropriateness of nodes as a data storage mechanism, and let me be clear that, while it's an important debate, it's not the topic at hand. There's also core's profile.module...but that's it's own whole can of worms that needn't be opened right now.

With the node-based solutions, the problem is at render-time: if you're storing a whole bunch of data about users in their corresponding node, then you've got to pick a render-time strategy for teasing out the particular subsets of data you want and arranging them on the page. Which either means doing it in the theme layer, or handing it off to another module first. Pushing the responsibility directly to the theme layer is just wrongheaded, in my opinion - it means that for any site implementing user-centric data pages, there's a task to be done which sits uncomfortably between a typical drupal dev and themer's toolset. Handing it off to another module first is the better option, because that module can make data-organizational level decisions, then present a consistent package to the theme layer. As far as I'm aware, Advanced Profile Kit is the only module that's really directly focused on that kind of logic for users. (Note that Michelle and I have been talking about this general idea for a while, and the long-term plan is to deprecate APK in favor of user_panels, which she and I would co-maintain)

But Users != Profiles, which begs the question: where does MySite fit in to the above discussion? It doesn't, really. MySite doesn't use nodes as a data storage mechanism, and it's not about building user profiles. It's more analogous to something like an iGoogle homepage - which in turn entails that it provide its own rendering logic for a DND interface. But it's still very much within the 'user-centric' scope. This disjointedness of these connections points to what I believe to be the second major problem with drupal's user handling: there are different conceptual axes along which any given user-centric page can be organized, and we're not always clear on which one we're talking about. Specifically, I see there being three axes: the user profile (bio/nodeprofile/content_profile, APK), the user homepage (mysite), and the user account page, which the core user module currently provides. Three, because of basic structural differences at the access level:

  • The account page is strictly user-facing; menu callback-level access is private.
  • The homepage is typically user-facing, with the potential for exceptions; menu callback-level access is semi-private.
  • The profile is public-facing, with the potential for restricting access to sub-components; menu callback-level access is public.

Note: There are some common exceptions to these access settings, but I'm not aware of any that can't be handled easily.

I don't know if this division has been explicitly articulated anywhere else, but its basic tenets strike me as being implicit in almost all of the discussions about Drupal's user handling. It's the conceptual underpinning over which many such discussions break down, because folks tend to (quite understandably) build a conceptual model of users based on the use case they've worked/are working from. Breakdown tends to occur over this problem: a piece of content that clearly belongs on the private account section/axis for Site A equally clearly belongs in the public profile section/axis for Site B. I think that core's existing system of providing user categories probably gets the gold star for best recognizing this reality, as it opens up the potential for implementing the user as a dynamic platform, viewable/interactable through many different lenses. Unfortunately, the core system crashes and burns on implementation.

A Platform: User Panels

There are a number of problems that a user platform has to solve if it's going to to better than core, more than just the ones I've described above. But they're a decent starting point, so I'll tackle the two major issues - node data retrieval & display, and handling of different user 'axes' - to begin with. A quick excerpt from earlier in the article:

...if you're storing a whole bunch of data about users in their corresponding node, then you've got to pick a render-time strategy for teasing out the particular subsets of data you want and arranging them on the page...Handing it off to another module first is the better option, because that module can make data-organizational level decisions, then present a consistent package to the theme layer.

That.Is.Panels. Minus the fact that Panels is not even remotely restricted to node data, it's a passable description of what Panels does: it grabs a specific bit of data and arranges it with respect to all the other pieces of data, all the while interacting with and presenting a consistent package to the theme layer. Problem 1, check.

The second issue is a little more complex, as it has to do with the way that Panels' context system works. But it's also the essence of user_panels-as-platform. I don't want to digress into the depths of the Panels engine, though, so I'll start with the final vision. PLEASE note that this description simplifies on a number of levels concepts for clarity & brevity:

  • Modules such as like nodeprofile, bio, content_profile, mysite, etc., would provide the content they create and store as pane types to be used by the Panels engine. (Things provided by core can be packaged into the user_panels module itself).
  • Through an administrative GUI, site admins can choose which (if any) of the different axes - private, semi-private, and public - get to use which of the various pane types provided by those modules.
  • Site admins can choose [system] paths at which each of these axes should reside, as well as whether or not to enable the semi-private or public axes at all.
  • Site admins can also set up how each of the displays for the axes should look, and set the override mode for each axis: either 'blueprints' or panels_page-style.

I'm hoping that the only particularly difficult thing to grok in that bullet list is the 'override mode'. The mechanics are pretty abstract and arcane, but in application, it's really pretty simple: imagine that we're overriding node/% with panels, and we're not doing any funky stuff with different displays for different node types. In this case, panels_page does overrides by using a single display for ALL those callbacks. That means there'll be exactly one row in the {panels_display} table, with one configuration, and EVERY single page request of the form node/% will call up the data from that row. Even if you've got 10 million nodes, they're all rendered through that one display.

In Blueprints mode, however, having 10 million nodes would mean that you also have 10 million displays. The difference is significant because it means that for each of those nodes, the node's owner is able to control how his/her node looks without affecting how any other nodes look. All the site admin does is create a 'blueprint' that provides all new nodes with a pre-configured display, that the owner can then change at will. In other words, everyone gets to control the appearance of their own node - or for our case, their profile, or homepage, etc. This is the paradigm under which og_panels operates.

Hopefully I'll have time to write up a little more about this paradigmatic difference, and potentially some efforts towards abstracting the process of writing a blueprints-based system (panels_page-style overrides are fairly straightforward by comparison), but that's all a separate blog post. For our purposes here, the bottom line is: Site admins can decide whether all user_panels are identical (created by the site admin), or if the users should be able to modify them.

Most of what needs to be done to make this a reality isn't actually that hard. We'd need to stitch together an admin interface, and pull in pieces of code that have already been written and tested in og_blueprints and panels_page. Abstracting the blueprints paradigm would be nice, too, but it isn't strictly necessary and can be done later.The only part of this whole idea that I think would be difficult is the very first bullet point in the list - writing the Panels integration for each of those modules. That's the part that'll depend on interest in this idea by the rest of the community.

Comments

Great writeup - this sounds

Great writeup - this sounds good to me!

One potential issue (that has come up for me more than once when building sites) - is that in addition to the private/semi-private/public axis, some sites might require 2 completely different layouts for the "user profiles" and the "user dashboard" pages (facebook is a classic example here). Functionally these are identical - users can add panes and so on - the lesson is that we should be careful not to limit 1 user=1 panel, since that doesn't alwayd fit.

Another thing that I think would be a fairly common requirement is a simple interface to allow end users to select public, "buddies only", or private for blocks - I think the admin interface should more be selecting (or restricting) which of those options the user has (if any), rather than presetting each block. Probably these are also hook based access controls anyway, since I can see several ways of structuring this (buddies, OG, roles etc).

I think the concept of overrides (and/or simple blueprints to start from) is important both from the point of view of simplicity and performance, but also from an administrator point of view. If you bring on some new functionality it is much easier to update a few blueprint panels and push it out to 95% of people, than to figure out a way to automatically change a zillion different panel instances.

One potential issue (that has

One potential issue (that has come up for me more than once when building sites) - is that in addition to the private/semi-private/public axis, some sites might require 2 completely different layouts for the "user profiles" and the "user dashboard" pages (facebook is a classic example here).

Ahh yeah. Sorry that wasn't clear: each of these different axes would have its own, unique panels display. It'd actually be a bit MORE difficult to make them linked. Still possible, but the ideal implementation of it would require some additions to the Panels engine that have crossed my mind, but are waaay down on my priority list atm. So, yeah - the idea here is, 1 user * 3 axes = 3 panels, or 1 user * 2 axes = 2 panels...whatever your use case requires.

...a simple interface to allow end users to select public, "buddies only", or private for blocks...

Fully agreed. Which is part of why I wrote the 'visibility' extensions to panels content_type plugins in May/June. The sample here is something I wrote originally for og_panels; it's logic that would govern visibility based on group membership. One other nifty thing - you'll notice that it statically caches the results of the initial query with all the possible results so that it never has to hit the db more than once per page request. That means if you've got 100 different panes on a page using that visibility callback, it'll be able to calculate visibility for ALL of them lickety-split off of only a single query.

There is a change that'd be necessary for the visibility system to work really nicely across a wide set of panes, though. Actually...now that I'm thinking of it, I should REALLY separate out visibility into a separate panels plugin. Right now, it's a little silly, b/c you have to declare all those visibility properties in the content_type plugin itself. It's also very difficult (read: impossible without hacking the plugin) to change the visibility logic being used by a content_type plugin that isn't yours. So they should really be abstracted out, and then options can be provided - as you've suggested - to site admins so that they can decide WHICH visibility logic the end user gets to pick from in their simplified interface. Buddies? Group members? Self-only? etc...

I think the concept of overrides (and/or simple blueprints to start from) is important both from the point of view of simplicity and performance, but also from an administrator point of view...

Absolutely - this is one of the arguments I often make in favor of blueprints. There's a benefit for the end-user as well, though - basically, it gives them a sandbox that they can play in and learn from without having to worry about if they can get back to where they started. Since their panel is part of one of these blueprint relationships, we can provide them a button that says, "Whoops, I screwed up. Revert to the base, please!" Better yet, the internal implementation of that will be identical for whether they're 'reverting' because they've screwed something up, or if they're just choosing to update to the most recent 'pushed' blueprint (if that's how the site admin has set blueprint pushes to work) - or even, reverting to some older blueprint that they like more than the most recent one. All possible through one mechanism.

Post new comment

The content of this field is kept private and will not be shown publicly.
  • Web page addresses and e-mail addresses turn into links automatically.
  • Allowed HTML tags: <a> <em> <strong> <cite> <code> <ul> <ol> <li> <dl> <dt> <dd> <blockquote> <h3> <h4>
  • Lines and paragraphs break automatically.
  • You may post code using <code>...</code> (generic) or <?php ... ?> (highlighted PHP) tags.

More information about formatting options