Problem/Motivation
In some cases, a particular site developer or a distribution developer using debut features will want to get the base functionality - content types, fields and the like - but not be bound by UI decisions. We should have a solution that makes those UI elements optional.
Relevant blog posts on how some distributions handle this: NodeStream, Voicebox.
What is a UI element?
- Menu items
- Contexts. (Context can be used to control non-ui reactions, but for the most part we're affecting UI elements like breadcrumbs, active menu items, and block display.)
Edge cases:
- Views? They definitely affect the UI, but they don't typically impose anything--unless they're providing a page override.
- Field display configuration? Yes, but in practice it's bundled with the field definitions, so hard to separate out.
So currently in Debut features we're probably talking menu items and contexts.
Currently we have a kludgey approach to menu items: we wrap them in an if module_exists('debut')) { test, and manually delete their entries from .info files. Sorta kinda makes them optional, but not an elegant solution. Also leaves features in an overridden state, see #1362130: Menu item approach leads to overridden features.
Proposed resolution
Options include:
- Pull UI elements into separate features. This could be done a la Voicebox, with individual UI items for each feature, or a la NodeStream, with general UI features bundling presentation from several base features.
- Default UI elements to disabled. This would remove them from the UI but allow e.g. a distro to selectively enable in alter hooks. Downside: they still show up in the admin UI.
- Set UI elements status based on a setting or settings. E.g., a variable debut_ui or featurename_ui (e.g., debut_article_ui), with options equivalent to enabled, disabled, and removed. Distros would set component defaults via manipulating these settings.
Remaining tasks
(reviews needed, tests to be written or run, documentation to be written, etc.)
User interface changes
API changes
Original report by neurojavi
Hello Nedjo:
I was about to begin my own feature based profile to improve my development workflow and was looking for a base feature set (or profile) to begin with. I discovered Debut and Openoutreach and I liked what you are doing here. I've been thinking about making my own feature set based in yours as a starting point (my initial idea) or collaborate with you in this project. I prefer the last option because I'm very interested and involved with the non-proft sector and have some interesting projects arround that.
But I have some questions about Debut Specification. My concerns are in relation with UI:
In some features (e.g. debut_image) there are contexts definitions that include reactions that change menu settings, set breadcrumbs and show some blocks (e.g. last images block). This is a decision about how to visualize a content type that, I think, are better suited for more advanced features (e.g. an image gallery feature). If you set them in the base features you are conditioning all complex features based on them. This also applies to menu items added by views (in this case installing a feature can have the side effect of adding a menu item to your site custom main menu)
I think that the base features have to be the basic building blocks and as such they must not have any UI additions like blocks, menu items and breadcrumb reactions.
Base features could provide all kind of blocks and other items but the visibility has to be set by other features like a generic openoutreach core feature, other advanced features and/or managed by the user in the UI (with the solution adopted by #885906: Define Debut Theme Specification )
What dou you think about this?
Many thanks for your effort.
Javi.-
Comments
Comment #1
nedjoReally good points. This is the key challenge: how to deliver out of the box functionality without hard-coding design choices.
One model is what Voicebox has done, http://code.funnymonkey.com/project/voicebox: divide features into sub-features (UI, navigation, views, etc.). See this blog post: http://funnymonkey.com/building-features-for-install-profiles.
Comment #2
nedjoMade menu items optional (created only if Debut module is present). See e.g. #1054288: Make menu item optional.
Comment #3
neurojavi commentedI read that blog post some weeks ago but I forgot about it... it's very interesting. I have voicebox already installed in my dev aegir box because I found its model very interesting. I'm going to re-read the code to learn something more!
I will write something more ASAP!
What do you think about opening a group in groups.drupal.org for debut (and another or the same for openoutreach?)
This way we can talk about generic dessing issues in a easiest way and give more visibility to the project... And it would be a good way to document the evolution of the project and how the decissions are made for future reference.
I have some ideas and a lot of questions and don't know in what queue can I post them.
Regards
Comment #4
neurojavi commentedHello again:
I've been thinking about that and testing your changes to make menu items optional in some debut features.
I think that there are better options. Making the menu items optional makes the interface (menu) dessing to rigid. And I don't see much more sense in making it depend on the core debut module as it would need to depend in a profile or other kind of thing, not in the core debut feature that needs to provide functionality to all other features, or that's what I think :-) )
I'll try to explain the architecture I have in mind:
1.- A core debut feature with basic roles, basic shared functions (as the ensure tags vocabulary function you use), and other basic and required objects. This feature must be a dependency for all other debut features and would be keep as minimal as possible.
2.- A feature for each content type (article, blog, etc.): This features contain only content type definitions, all kind of useful page and block views, basic permissions and comment settings. They *don't* contain menu items, path-auto settings, breadcrumbs, contexts and anything else.
3.- A feature for each particular functionality, as you have done with WYSIWYG, social and others (but withot any menu links, etc.)
All this features will be the basic building blocks and all of them could be sure that the basic roles and vocabularies exists. If a user (or profile) doesn't want or need this basic roles he could rename, ignore or delete it, but he would have a basic pattern for assigning permissions to his own roles.
Over that, you can build another features that require (depend on) the building blocks they want and can assign menu paths, breadcrumbs, contexts or whatever you want. This second level has to be better defined (one big feature at profile level, a few reusable ones...?) in the future but the basic features are very clear to me.
This is the model I has been thinking of for some weeks and is very similar to the implementation done in voicebox.
What dou you think?
Javi.-
Comment #5
neurojavi commentedComment #6
nedjoYes, we need to increase UI flexibility, but I'd like to retain:
1. Features work out of the box with at least one integrated and consistent UI approach, e.g., the currently implemented one, without the need to install with a particular install profile.
2. We don't have to add separate UI features for each feature--there are already enough features without doubling the number.
An approach I'm considering is to have features describe themselves in ways that allow integrating modules to build UIs. E.g., debut_event might implement a hook:
On this basis, an integrating module can programmatically generate UI elements like menu items and contexts.
Comment #7
neurojavi commentedAnd what about making each current feature project a package with two features inside. An example:
debut_article project will contain two features:
* debut_article_basic: Basic feature with the content type, field definitions, views definitions, strongarm variables not related to UI, captcha settings, etc.
* debut_article_ui: UI feature with contexts, pathauto, strongarm vars, menu definitions, etc.
The UI feature will depend on the basic one, so user only have to install a package (debut_article) and enable one feature (debut_article_ui). Advanced user or profiles can enable only basic ones.
This is very similar to what FunnyMonkey did in Voicebox as explained in the link you provided in #1: http://funnymonkey.com/building-features-for-install-profiles
With this approach you have the advantages of two worlds (basic user use and advanced user/profile use) but you don't need to maintain two projects for each feature.
Any other approach to this (AFAIK) will be too tricky... I don't want to disable menu items, change default menus, override path settings or things like that to provide basic functionality to my profiles. This doesn't worth the effort. It's easiest for me to make my own feature set. But I'm really wishing to contribute this project and not starting my own private clone...
I think this solution can make debut much more suitable for other uses beyond basic user "download and enable" and openoutreach profile use cases.
Javi.-
PD: I don't see how the hook in #6 can help... If I install a debut feature to use it a more advanced site I'll need to read the feature code to manually create contexts, paths and the like. Could you elaborate on this?
Comment #8
Grayside commentedYour hook there seems pretty elaborate, and will hinder the ease of simply working with Features. One thing you might do to establish a common UI is to replace the idea that any given module should implement hook menu. Instead, have a hook_debut_admin_settings() that any feature can implement, and which will be aggregated as a fieldset of a Debut Settings form for that feature.
I did just such a thing in the hook_ucsb_toolkit_settings() where "ucsb_toolkit" was my equivalent to the debut base module. See aggregation of forms here.
At that point any integrating module can use a hook_form_alter() to modify any feature-provided UI as normal.
For things like menu links, breadcrumbs, and so on... part of the challenge of integrating features is knowing all the hooks. Rather than provide overly verbose info hooks, I suggest writing a guide on the many alter hooks available when working with exportables (planning a blog post on this subject actually...) Don't like a breadcrumb setting? Alter that reaction away. Or change it.
Comment #9
nedjo@Grayside: thanks, those are great suggestions. Thanks for the links, I'll look at your approach.
Comment #9.0
nedjoUpdate issue summary.
Comment #10
nedjoComment #10.0
nedjoUpdated issue summary.
Comment #11
nedjoI'm in the process of pulling menu items from features into .install files, so they can be changed or deleted without overriding the feature.
Comment #12
nedjoThe approach in #11 was unsuccessful--because the views in question were not present at install time, menu items weren't created.
Instead, I'm putting the menu items back into the views. This is at least better than the previous approach because (a) menu items can be edited via the menu admin system without leaving the feature in an overridden state and (b) if desired, another module can alter the default view to remove or alter a menu item.
Comment #12.0
nedjoAdd link to #1362130.