Setting up a reasonable development environment

  1. Install drush
  2. Turn on administration menu items at admin/atrium (check the "Show all administration pages" checkbox)
  3. Enable devel module

Checklist

  1. Build feature (CCK, Views, Context, etc. and exported using Features module), can be done on non-atrium site
  2. Add feature and dependency modules to codebase in admin/modules/contrib and admin/modules/features
  3. Enable your feature
  4. Add spaces metadata to feature .info file
  5. Add spaces filters, access control to feature views and to any custom menu callbacks
  6. Export any necessary variables (node type settings, etc.) using strongarm
  7. Export any necessary user permissions
  8. Add any dashboard blocks to hook_atrium_dashboard()
  9. Add icon, CSS with drupal_add_css() in hook_init()

Step-by-step

1. Build feature

Features can be built using common Drupal.org site building modules (Views, CCK, Context, etc.) but you can also leverage other specialized modules like FeedAPI, Faceted Search, etc. For an overview of how to build a feature you can watch the screencast Making and Using Features in Drupal. For the rest of this HOWTO I will be using the Imageboard feature built in this screencast as the example feature.

2. Add feature and dependency modules to codebase

Next we'll put our feature module and its dependencies in the Atrium codebase. We'll untar the imageboard feature to

sites/all/modules/features/imageboard

And its dependencies imagefield and filefield to

sites/all/modules/contrib/imagefield
sites/all/modules/contrib/filefield

3. Enable your feature

Next, we'll enable the dependent modules imagefield and filefield and then the Imageboard feature on admin/build/features.

4. Add spaces metadata to feature .info file

Next we will add some metadata to the feature's info file to let Spaces know that the feature can be used with Spaces.

core = "6.x"
package = "Features"
project = "imageboard"
name = "Imageboard"
description = "Imageboard with commenting."
...
spaces[types][] = "og"
spaces[types][] = "user"

If you'd like your feature to offer a menu item that spaces can toggle on and off add a line for it

features[menu][] = "imageboard"

You can specify each type of space that the feature is compatible with or say that the feature is compatible with all space types by using the following line:

spaces[types] = "all"

Finally, clear your cache with a

$ drush cache clear

and turn on the feature in one of your groups.

5. Add spaces filters, access control to feature views and to any custom menu callbacks

The imageboard feature is pretty usable at this point but you'll notice a few problems. If you enable the feature in two groups, you'll see that any groups can see the images posted in the other groups. We need to add a view filter to limit the imageboard view to nodes only in that space. In addition, we need to add an access plugin so that even when the feature is off users cannot access the imageboard by typing mygroup/imageboard into the url.

  1. Go to admin/build/views and edit the feature view
  2. Add the Node in current space filter (or User in current space if you are building a view of users)
  3. You probably want to set the "When not in a space" dropdown to "Hide all results." "Show all results" is useful for blocks that may be seen in a space and outside (e.g. in the site dashboard).
  4. Click on Access under the view's Basic settings and choose the Spaces feature plugin. Choose your feature in the next dropdown. This will ensure that this view is only accessible when enabled for a given space.

Do these steps for each of the views in your feature. Also note that if you have built any views that don't use node as their base table (e.g. comments), you will need to add a relationship back to the node table to enable access restrictions (use the node access filter) and to filter content for the current space.

6. Export any necessary variables (node type settings, etc.) using strongarm

Strongarm is a module that lets you enforce variable settings that are necessary for your feature to work properly. Some of the most common variables you'll want to export are your node type settings. You can look at all the variables that might relate to your node type using the following drush command:

$ drush strongarm | grep _image

atrium_update_type_image
comment_anonymous_image
comment_controls_image
comment_default_mode_image
...
content_profile_use_image
feedapi_image
feedapi_settings_image
form_build_id_image
node_options_image
notifications_content_type_image
og_content_type_usage_image
show_diff_inline_image
show_preview_changes_image
upload_image

To find out the value of a variable (or multiple variables in this case), you can use

$ drush strongarm atrium_update_type_image node_options_image

array (
  'atrium_update_type_image' => 1,
  'node_options_image' =>
  array (
    0 => 'status',
  ),
)

You can then export the variables by copying and pasting your strongarmed variables into hook_strongarm(). You can implement this hook and other custom hooks in imageboard.module which will be left alone by the features module when running drush features update (or updating in the UI).

/**
* Implementation of hook_strongarm().
*/
function imageboard_strongarm() {
  $conf = array (
    'atrium_update_type_image' => 1,
    'comment_anonymous_image' => 0,
    'comment_controls_image' => '3',
    ...
    'feedapi_settings_image' => array('enabled' => 0),
    'node_options_image' => array('status'),
    'show_diff_inline_image' => 0,
    'upload_image' => 0,
    'notifications_content_type_image' => array(),
  );
  return $conf;
}

7. Export any necessary user permissions

Your feature will likely want to set up sensible permissions out of the box. Atrium comes with 4 different user roles and features should try to stay away from adding additional roles if possible:

  • anonymous user (no access)
  • authenticated user (can join groups and use features normally)
  • manager (has access to make, configure and manage groups)
  • admin (has access to sitewide configuration, maintenance)

Once you've configured the permissions your feature needs for these different roles, you can export your permissions by adding them to imageboard.info:

features[user][] = "create image content"
features[user][] = "edit own image content"
features[user][] = "delete own image content"

Then run

$ drush features update imageboard

And you'll see that the hook_user_default_permissions() has been added to imageboard.features.inc.

8. Add any dashboard blocks to hook_atrium_dashboard()

Your feature can provide additional dashboard blocks by implementing hook_atrium_dashboard in imageboard.module:

/**
* Implementation of hook_atrium_dashboard().
*/
function imageboard_atrium_dashboard() {
  $blocks = array();
  $blocks['views_imageboard_comments-block_1'] = array(
    'module' => 'views',
    'delta' => 'imageboard_comments-block_1',
    'weight' => 20,
    'region' => 'right',
  );
  return $blocks;
}

The format is similar to that of exported contexts. You can limit the block to only show up on user space dashboards (or any other space type) by adding

'spaces' => array('user', 'og'),

To each block's entry.

9. Add icon, CSS with drupal_add_css() in hook_init()

Your feature can provide its own menu icon and any custom CSS by adding a stylesheet in hook_init():

/**
* Implementation of hook_init().
*/
function imageboard_init() {
  drupal_add_css(drupal_get_path('module', 'imageboard') .'/imageboard.css');
}

Icons should be 40x40 PNG-24 files.

The CSS for your icon will look like this:

#features-menu li a.icon-imageboard span.icon { background:url(images/icon.png) no-repeat; }

Note that the class .icon-imageboard is generated based on the path of your menu items. If you have multiple menu items, you can specify a separate icon for each based on the path class.