Features
Building Features for Install Profiles
Posted August 18th, 2010 by BillWhen we originally set out to build a set of Features to support the install profile of our Knight Drupal Initiative work, we figured we would use Context to drive the creation of these features.
And this almost worked. Almost.
The Challenge
The challenge we faced in working with features involved sorting out the way Features manages dependencies. When you're setting up a feature, and especially when you're setting up a feature based on a context, the dependencies are automatically brought in and generated for you. So, most of the things that the context relies upon are automatically made a part of your feature (and Strongarm can generally grab the rest). This is great if every single one of your contexts is a completely standalone item. But, if anything in your context contains (for example) a UI element that connects over and exposes functionality that is contained within another context, then you will have two features with overlapping dependencies, and this creates conflicts.
The Goals
At the outset, we had four main goals in setting up our install profile, and the related features used within the profile.
- Create a site that someone could install and start using;
- For site maintainers/non-developer admins, make features easy and intuitive to use by creating a logical set of dependencies; aka, features should contain modular sets of functionality, and be as small and as lightweight as possible;
- Retain the ability to use features to track changes in site config over time. One of the huge benefits of Features is the ability to track changes that you make in config; using the Diff module brings more of the awesomesauce, and here at FunnyMonkey we are serious about the awesomesauce;
- Make features that are as reusable as possible.
Some Other Things That Didn't Work
Briefly, we contemplated shipping an install profile with one enormous feature. Technically, this works, and the install would have been simple, but the maintainability of this arrangement could potentially get complicated over time. Additionally, one feature that holds everything is not particularly reusable, and it doesn't reveal a clean site architecture through a set of clearly defined and managed dependencies. So, while this would have worked, and is a viable approach in some use cases, it didn't align with our goals.
The next option we considered was to use Features to define functionality, and document how to use the Context module to control block visibility and create a coherent UI to connect the various corners of the site. This would have achieved our goal of making reusable features, but it would have required non-technical users to interact with the Context UI in order to get the most from the site. Given that one of the goals of the entire Knight Drupal Initiative is lowering the barrier to entry for newer or novice users, this approach didn't seem viable either.
Hey! You Put Your Feature In My Module!
One of the many cool things about features is that it pushes config to code; to put it another way, it creates a module from config options. Like modules, features can declare dependencies. So, with this in mind, we exported some initial features that contained the overlapping dependencies as defined above. Then, we edited the exported features so that they contained just the components we wanted them to have - this process included removing the overlaps, and maintaining dependencies on both modules and other features. This allowed us to create some base features that contain the central keys to delivering the functionality - things like content types, imagecache settings, fields, etc. Then, we created some extras features that contain - for example - various views, flags, and other mechanisms used to organize information on the site. Finally, we created UI features that contain the contexts and the reactions that display specific blocks on specific pages.
As we worked on the initial site build - and the subsequent revisions of that build prior to building out features - we also paid careful attention to tags, and to maintaining some consistency with how we tagged and organized our views and contexts. This meta-organization of the building blocks within the site helped us as we got down to organizing the build into features and an install profile.
To get a sense of how this comes together, look at the screenshot below.
This page is pulled together via multiple different features, and they are tied together with a final UI feature.
Using this approach, we are able to meet all of our goals as defined above. Additionally, by separating the functionality from the UI that exposes that functionality, we provide more flexibility for people to use whatever means they want to display content. On our site, we use Context to control block visibility and other display settings. However, someone else could just as easily leave our UI features turned off and use Panels, and/or Drupal's core block visibility settings.
For another example, the home page of the site ships with a slide show, and content displayed within vertical tabs (the base theme we are using for this site is Hexagon; there is some real loveliness in there, but that's a topic for another post). This homepage is generated via a UI feature; if someone wants this UI, they can turn it on. Or, people can build out swappable home page UI features that build on the underlying components, and manage these changes via the features UI.
The down side of this approach, of course, is that you can't use the Features UI to build your feature, and the process of defining dependencies manually requires some quality time with Strongarm and the variables table.
Ideally, we could control or manually override dependencies using the Features UI, but patching Features to provide manual overrides of dependencies is no small task, and would likely come at the expense of usability.
By treating features like the modules they are, and by setting up dependencies between them, we can create small, reusable building blocks that retain the maintainability of features created via the standard Features UI. We are getting ready to release our install profile that incorporates this method of building and maintaining features; we still have some testing to do to make sure that we haven't missed or overlooked anything. And with that said, there are likely other ways of solving this, and we would love to hear about them.
Making Better Documentation, and Making Better Sites
Posted June 2nd, 2009 by BillPart of our work for the Knight Drupal Initiative includes work to lower the barriers to getting started using Drupal sites to power community-driven media. As we work toward this end, we have multiple tools at our disposal, including:
- Better documentation, for both site administrators and people using the site
- Easier installs, to allow people to enable more complex functionality with less work
- Easier and more flexible theming
At the risk of stating the obvious, the work we do for the Knight Drupal Initiative will also be immediately transferrable to all of Drupal development.
Getting Started: Journal
The Journal module allows us to keep a running record of changes made on a Drupal site. Currently, it allows you to take notes as you build out your site. It's a great tool to track the specific steps people take as they work within a site.
We will build out two additions to Journal:
1. Tag journal entries, which would allow us to create categories of journal entries. For example, while configuring the WYSIWYG API to work with Filefield and Filefield Insert, we could tag these entries as "Text Editor" -- later, this would allow us to see exactly how the editor was configured.
2. Export journal entries by tag or by date range, in csv, ordered list, or unordered list format. This would allow us to generate documentation on how sites are built. This documentation can be used on drupal.org, for site administrators as sites are delivered, or to create end user documentation.
By way of example, let's say we have built a site that is designed allow teachers to create online portfolios as part of professional development. Prior to delivering the site, we could walk through the steps of creating a portfolio. At each step, we would comment on the process of creating the portfolio using the Journal module. We would tag each entry as "portfolio creation." Then, once all the steps have been completed, we would export the steps as an ordered list, and voila, we have our end user documentation.
Moreover, this process also gives us the instructions and order we need to develop functional tests using Simpletest.
With these additions to the Journal module, we will have the base package for creating more comprehensive documentation about all aspects of building and using a site. However, one of the challenges of documenting a site build is getting the documentation into the hands of end users, or people not directly involved in the build. Often, comprehensive documentation can be overwhelming as it floods someone with information.
Inject Me!
The Advanced Help Injection module builds off the Advanced Help module, and allows us to draft documentation using Drupal's core book module. Then, the documentation can be inserted on specific pages within a site, so people only see the documentation they need when they are at a place where they need it. So, the documentation generated using the Journal module can be presented to people exactly when it makes the most sense.
And finally: Advanced Help Injection allows the documentation to be exported as a module. So, all the documentation can be pushed to code, and delivered with the site. This brings us closer to the goal of having a site that is self-documenting, for both site admins and end users.
Moreover, the process of creating these tools can actually be documented using the tools themselves. While it feels like a blend of eating our own dogfood and chasing our own tail, it works.
What Are We Documenting, Anyways?
In this post so far, we have looked at simplifying the task of creating documentation, and using existing tools to get that documentation to people in a more efficient way. However, documentation assumes featuresets, as we can't have documentation about what to do without something to do.
This is where we cue the Features module. Take a minute to check out the latest post illustrating the power of Features over on the Development Seed blog.
As the video and post shows, the Features module allows us to create bundles of featuresets that can be moved from site to site. We envision a system where two things happen:
- Featuresets are paired with documentation, so that any set of features can be accompanied by inline documentation; and
- The process of creating new sets of features is fully documented using the Journal module, to empower more people to build and share features.
Making It Look Pretty
Theming and design are both enormous categories, so I'll be brief. In parallel with the work described here, we are working with Joon Park to build out a base theme (currently named Annex, but it might get changed to Mango Smoothie for the official release) that simplifies the process of creating a unique look and feel for your site. For end users, it supports some simple eye candy out of the box; as one example, it has multiple block regions, including some that support accordion and tab effects by default. For themers and designers, the process of inheriting features from the base theme to subthemes has been overhauled and simplified, allowing people more control and flexibility in building sub themes. More to come on this; ideally, we will have a release at some point in June.






