Lenses (selecting a subset of fields from a node)

We encourage users to post events happening in the community to the community events group on https://www.drupal.org.
David_Rothstein's picture

I'm working on an idea for a new module and was wondering if anyone had any feedback. It may overlap a bit with existing modules (especially Views), but I think it's different and potentially interesting.

Basically, the idea is this: Sometimes, when viewing/editing/creating a particular type of content, you might want to do so through a "lens" that only shows you a subset of fields that you are interested in at that particular time. You only want to deal with those particular fields, without having to deal with the node as a whole (which may be very large and complex).

Maybe this is best illustrated with an example. Suppose you have a content type "food" with a whole bunch of fields: "meat", "poultry", "fish", "fruits", "vegetables", "grains", etc. Now suppose some vegetarians visit the website and we want them to be able to focus on editing the "fruits", "vegetables" and "grains" fields (the other stuff would just be a distraction to them).

So we want them to be able access a page (maybe something like /node/123/vegetarian) where they see a version of node/123 that only shows their fields of interest and hides the rest. Similarly, we want to give them a simplified node edit/submission form (maybe at /node/123/vegetarian/edit) where they can edit their fields of interest without having to scroll through other fields they don't care about.

Presumably, lenses would be defined in terms of fields rather than content types. In other words, once you have a "vegetarian" lens defined, you could apply it to any content type you want. So if you have another content type on your website, let's say "things that start with the letter V" (bear with me here ;), with fields "violins", "vegetables", "voting booths", etc., then applying the same vegetarian lens as above would pull out the "vegetables" field only.

Does this make sense? Are there any existing modules that make it easy to do this? Some possibly-related modules that I'm aware of include:

(a) CCK Field Permissions. The main difference, though, is that we don't necessarily want to restrict certain fields from being accessed -- the vegetarians may very well sometimes want to view/edit the full node rather than limiting themselves to the vegetarian fields. Similarly, even people who aren't vegetarians may sometimes want to view/edit a simplified version of the node that focuses on the vegetarian items.

(b) Formfilter. Also similar, but it only works on forms, and it seems to only let you make a simple yes/no decision about whether each field will be filtered out -- there's no way to have multiple "lenses" for the same form.

(c) Views. There are definitely similarities here, and it might even be possible to reproduce the entire functionality of a lens using Views; however, it seems a little clunky. I'm no Views expert, but it looks to me like you would need to create two (or even three) different Views, one for displaying the nodes and one for editing them (and for the latter you would have to use something like Editview or Editablefields), plus you would be limited to a List or Table View because those are the only ones that let you choose fields. Overall, it seems to me that this isn't a natural fit for Views, because Views is mainly designed for selecting a list of nodes from the website, whereas "lenses" are about selecting a list of fields for a particular node. So in some ways I think the idea of lenses could complement Views and maybe improve/replace the "Fields" option that Views currently has. In other words, you could create a View that selects a set of nodes and then applies a particular lens to them, so that all nodes within the View only show a certain subset of their fields.

Anyway, I'm interested in this functionality for a couple different sites I'm involved with -- and for totally different reasons on each site, so it seems like maybe it's something that could have a wide range of applications...? I'll consider starting to code this soon, but since it will be my first (real) module, I could definitely use some help and/or suggestions ;) Thanks!

Comments

Screenshots of the Lenses module

David_Rothstein's picture

Just bumping my own post and mentioning that the module is almost ready to release. It turned out to be a much bigger project than I anticipated, but I think I've managed to create a configurable and (hopefully) useful solution to the general problem of how to present the same piece of content more than one way on a website... allowing you complete freedom to show or hide "fields" (by which I mean core Drupal fields such as title/body, in addition to CCK fields and Taxonomy vocabularies) in different settings, as appropriate.

I'll post some code soon (and eventually put this on drupal.org, of course), but I still have to tidy up a few things. I'm still very interested in feedback and ideas, if anyone has any. (Integration with Views 2 is something I'll be very interested in for Drupal 6, probably by making lenses available as a row plugin.)

Since screenshots are better than words, here is a small example of the Lenses module in action:

Only local images are allowed.

You can see that the entire node (i.e., the entire lasagna recipe) is visible under a menu tab, but there are other menu tabs (a.k.a., the "lenses") that only show some of the fields, thereby allowing you to focus on parts of the recipe without having to see the whole thing. Note that the same thing can be done on the node edit/create form, by the way. The module also comes with a permissions system, so if you wanted to hide the entire recipe but allow users to see some individual parts of it, that's possible too. It's also worth pointing out that the same field can easily appear in multiple lenses; for example, "preparation time" (circled in red) is a field that show up under the recipe's directions, but also might be useful in a quick summary of the recipe, as below.

Only local images are allowed.

quick UI suggestion

amitaibu's picture

Nice idea.
The way i see the UI is: admin/content/xxx/lens:

  1. Lens name
    2.1 Fields
    2.2 User role/ permissions allowed per field - it seems CCK for D6 now comes with per filed permissions,

Is that would you had in mind?
How are you going to deal with fields groups?

A few more details

David_Rothstein's picture

Thanks for your comments and suggestions!

First of all, I think my description of the permission system wasn't written so clearly the first time. I'm not planning to implement "per-field" permissions in this module, but rather "per-lens" permissions. In other words, I've set it up so you can deny access to a lens on a per-user-role basis (for example, you could hide the "Directions" menu tab in the above screenshot from some users), but they still may be able to access some of the fields in that lens in other contexts (e.g., the "Summary" menu tab will still let them see the "Preparation time" field).

I think it will be possible to use Lenses to completely hide some fields from certain roles (by cleverly controlling which lenses they have access to and which fields are in those lenses), but that's probably only a good idea if the fields are being hidden for aesthetic reasons. If the goal is security, then the right way to do it is still through a separate field permissions module (and thanks for pointing out that this might be in CCK itself in D6 -- I didn't realize that was a possibility). And the Lenses module will definitely "play nice" with field permissions modules, since internally, it never specifically grants access to any field -- it only denies access to all fields that aren't part of the lens.

Regarding field groups, that's a good question... as things currently stand, the module is aware of field grouping on a fundamental level, in the sense that when it goes out and collects information about fields, any field can declare itself as "group" that contains other fields. (As I've implemented it now, all CCK fieldgroups declare themselves as "groups", of course, but I've also defined a group for Taxonomy -- this controls the entire taxonomy fieldset as a whole, rather than on a vocabulary-by-vocabulary basis).

I'm still trying to decide the following, though: If you click a checkbox to specifically include a group in a lens (or to specifically exclude the group from the lens), what does that mean for the individual fields inside that group? Suggestions are welcome, but I think the simplest way to handle it might just be that including/excluding a group automatically includes/excludes all the fields it contains. (Putting a group in a lens is therefore sort of a brute force tool.)

As for the overall UI, the basic list you started making is similar to what I had in mind (actually, the form for adding a lens is the one big part of the module that isn't written yet, which is why I haven't bothered posting any code yet!). But in terms of functionality, some of the things that the module can already do internally (and therefore which will actually show up on the form once I finish writing it) include:

  • Lens name
  • What to append to the URL to access the lens (e.g., node/123/view/something)
  • List of fields
  • Where should the lens apply (viewing a node, editing a node, creating a node, or any of the above)?
  • What content types should it apply to?
  • Who should be able to access it? (can restrict by user role, or also make it a "private" lens that only the person who created it can use)
  • Whether to make the lens override the default menu tab (e.g., to have it visible at node/123, node/123/edit, etc... as opposed to the default view which shows all fields and that is normally visible at that URL)
  • etc.

Any other possible options people can think of?

D6 permissions -

amitaibu's picture

D6 permissions - http://www.tejasa.com/node/167
I think it makes more sense for per-field. What if i want "Directions" to appear for all users but diiferent fields - like views is 2 is going to do.

other things sound cool.

After rethinking you are

amitaibu's picture

After rethinking you are correct, you should do per-lens, as per-field should be handeld by a field-access module.

btw, this workaround also allows getting the lens functionality (using panles integration for your module is probably a good idea).

Ah, great, I'm glad we agree

David_Rothstein's picture

Ah, great, I'm glad we agree ;) I think by combining per-lens permissions here with per-field permissions from another module, that ought to cover most of the possible use cases for showing/hiding fields.

Thanks for the suggestion about Panels integration; that sounds like a great idea! I hadn't thought about that before, but you're absolutely right -- it definitely would make sense to be able to apply a lens to a node inside of a panel. My number one concern at the moment is getting a basic working version of Lenses out for Drupal 5 (which I hope will be in a manner of days rather than weeks, but we'll see)... but after things stabilize with the various other modules for Drupal 6, I think Views 2 and Panels 2 integration should absolutely be the first new features to add to this module.

And yes, it does indeed seem that there might be some workarounds for getting the basic idea of a lens... both with Views and, as you say, Panels/CCK Blocks. But the workarounds don't seem so simple, so I'm hoping that the idea of a separate Lenses module will gain some traction. I think the reason for separating it is that the idea of a "lens" is really a more fundamental concept related to the underlying data structure: it's really about defining a relationship between different fields, which can then be reused in different contexts wherever and however you are displaying a node.

build mode in D6

moshe weitzman's picture

This notion that there are different field subsets for a node is built into Drupal6 and into CCK for 6. Search the code for $node->build_mode or see the tabs and subtabs on the Display page of a content type (requires CCK). It would be handy for a module (why not lens?) to let the user make own $build->mode. Then the admin would use the Display tab to customize it.

quite true - cck could call

yched's picture

quite true - cck could call a hook that lets a contrib module define additional 'render modes', include them in the UI for 'display fields' and store their display settings.
We then come quite close to Jeff Eaton's initial idea of 'rendering styles' (http://drupal.org/node/144608).

Excellent! Thank you for

David_Rothstein's picture

Excellent! Thank you for the tip, Moshe. (I had a feeling I wasn't the first person to think about grouping fields together like this, but I hadn't come across anything... that build_mode parameter is pretty well hidden.)

So at a minimum, the D6 version of Lenses should set $node->build_mode to a unique value for each lens, so that other modules know the node has been built in a unique way. (And then if CCK provides a rendering hook as yched suggests, it should also implement that.)

In the long run (maybe around Drupal 8..), it sounds like the "display" aspects of a lens could be completely handed off to CCK/other modules, but for now, I think they probably still need to be separate (for several reasons, among them the fact that I'm supporting some "fields" that aren't yet part of CCK, such as taxonomy... and I'm also allowing lenses to be applied to a node edit/create form, etc).

However, as you suggest, this is still a great combination. The way I'm now picturing the workflow is:

  1. The node is loaded.
  2. The Lenses module applies a lens, removes certain fields, and marks $node->build_mode with a unique ID.
  3. CCK (and maybe Contemplate, eventually?) render the node using a unique display tied to that particular value of $node->build_mode.

So a site admin could set things up so that an individual field is rendered/displayed one way when it appears in lens A, but in a totally different way when it appears in lens B. Nice!

Nice

Michelle's picture

I missed this when it was first posted and am glad to see the module is now nearly ready. I think this could come in handy for user profiles where there is the potential for a lot of fields. Rather than break them up into separate nodes and have to deal with the issues that come with that, this would let you break things up more on a single node. I'll have to play around with it when you release it.

Michelle


See my Drupal articles and tutorials or come check out the Coulee Region

Thanks, that sounds like a

David_Rothstein's picture

Thanks, that sounds like a great use case (as long as you're using Node Profile or something like that).

Hopefully Lenses will work really well for any situation where you're building a complex node with lots of fields. (Actually, one of the use cases I originally had in mind was the possibility of using Drupal to store scientific data. There, an individual scientific observation -- the node -- can easily contain hundreds or even thousands of measurements or pieces of data -- the fields. You definitely would not want to put that on the screen all at once.)

A possible use case...

flickerfly's picture

Just thought I'd pop in with a use case. I'm imagining using this to provide the same form for two different types. For example, providing a single persons view of a form that has elements for the spouse to fill out. Only having one form to maintain, but being able to have both views would make a lot of people here happy. :-)