Advanced Open Atrium customization

Antonio De Marco
17 Dec 2010
15 Comments
Antonio De Marco
17 Dec 2010
15 Comments
Antonio De Marco, 17 Dec 2010 - 15 Comments

Advanced Open Atrium customization

Make your Open Atrium behave as you want, the code-driven way

Open Atrium comes, out of the box, with a rather complete set of features which allow to bootstrap a functional intranet solution in a few minutes. Still, to be actually usable in a real life context, an Open Atrium installation must be adapted to each organization's needs and structure.

In this article we will learn how to customize an Open Atrium installation in a code-driven fashion, without hacking its core and making sure that an upgrade to a newer version will not swipe away our valuable changes; we will cover:

  1. How to add custom user profile fields;
  2. How to override Atrium's core configuration;
  3. How to create custom group types.

For a smooth reading you should be familiar with Features and Exportables concepts. If you are not, just check out our Code Drive Development blog post series.

1. How to add custom user profile fields

One of the greatest changes introduced with the Features module 1.0 stable release is that, when exporting, you can actually decouple CCK fields definition from the node type they belong to, or in other words: CCK fields and node type can be exported to different features.

As a direct consequence of this approach we can store our custom user profile fields in a feature (call it custom_profile) that extends the Atrium's core atrium_profile. Let's have a look to its .info file:

core = "6.x"
dependencies[] = "features"
dependencies[] = "text"
description = "Custom profile feature."
features[content][] = "profile-field_profile_city"
features[content][] = "profile-field_profile_country"
name = "Custom Profile"
package = "Features"
project = "custom_profile"
version = "6.x-1.0"

This makes sure that, when Open Atrium will be upgraded, we will still find our custom fields (namely "City" and "Country") since they belong to the custom_profile feature.

2. How to override Atrium's core configuration

The Features module exposes several hooks that alter the default settings of exported components, like variables, permissions, contexts, spaces, etc... A correct use of these hooks makes it possible to safely override default component settings being sure that they will not get lost after an Atrium core upgrade.

Let's say we want to change the system's default user picture: Open Atrium stores it into a variable, so all we need to do is to implement hook_strongarm_alter() and override its value:

<?php
/**
* Implementation of hook_strongarm_alter()
*/
function custom_profile_strongarm_alter(&$items) {
  if (isset(
$items['user_picture_default'])) {
   
$items['user_picture_default']->value = 'sites/all/themes/custom/user.png';
  }
}
?>

After clearing the cache we will see our new user picture appearing everywhere on the site. Same goes for the default blocks we have on the dashboard of a newly created group: we can choose, for example, to replace the "Welcome" video with the "Latest discussion" block. Here is how to do that:

<?php
/**
* Implementation of hook_spaces_presets_alter()
*/
function custom_group_spaces_presets_alter(&$items) {

 
// Store a reference to our target block section.
 
$blocks = &$items['atrium_groups_private']->value['context']['spaces_dashboard-custom-1:reaction:block']['blocks'];
 
 
// Remove "Welcome" block.
 
unset($blocks['atrium-welcome_member']);

 
// Add "Latest discussions" block.
 
$blocks['views-blog_listing-block_1'] = array(
   
'module' => 'views',
   
'delta' => 'blog_listing-block_2',
   
'region' => 'content',
   
'weight' => 1,
  );
}
?>

After clearing the cache all new groups (and those that didn't have their dashboard customized by an user) will inherit the new settings. If we now have a look at our features status we'll see that several Atrium core features have been marked as "Overridden":

$ drush features

Name                 Feature              Status    State       
Atrium               atrium               Enabled   Overridden  
Atrium Activity      atrium_activity      Enabled               
Atrium Blog          atrium_blog          Enabled     
Atrium Notebook      atrium_book          Enabled               
Atrium Calendar      atrium_calendar      Enabled               
Atrium Case Tracker  atrium_casetracker   Enabled               
Atrium Groups        atrium_groups        Enabled   Overridden  
Atrium Members       atrium_members       Enabled   Overridden  
Atrium News          atrium_news          Enabled               
Atrium Pages         atrium_pages         Enabled               
Atrium Profile       atrium_profile       Enabled  

This is a totally safe situation since your configuration has been altered via code, thus it is 100% upgrade-safe. To learn more about altering default hook have a look at Feature's feature.api.php file.

3. How to create custom group types

In the example above we learnt how to replace a block in the default "Private group" space preset. What if we need a completely new group type, with custom features and specific configurations, something that we cannot really map into one of the two group types ("Public group" and "Private group") provided by Open Atrium? Easy, we just need to provide a custom space preset that describes the kind of group we need.

For example: we want to have a "Portal group" which will be used as the public website of our organization, it will have news and static pages and it must look slightly different than the intranet. The Spaces module is powerful enough to allow you to turn each group into a completely different website, customizing settings, menus, theme, etc...

To do that, we start by cloning the "Controlled group" space preset into our new "Portal group" preset. We then export it to a new feature called atrium_portal, having an .info file similar to:

core = "6.x"
dependencies[] = "atrium_news"
dependencies[] = "atrium_pages"
dependencies[] = "context"
dependencies[] = "menu"
dependencies[] = "spaces"
features[context][] = "layout_portal"
features[ctools][] = "context:context:3"
features[ctools][] = "spaces:spaces:3"
features[menu_custom][] = "menu-portal"
features[menu_links][] = "menu-portal:calendar"
features[menu_links][] = "menu-portal:dashboard"
features[spaces_presets][] = "atrium_portal"
name = "atrium_portal"
package = "Features"

As you might have noticed, the file contains a dependence on two features that are not part of the Open Atrium core: atrium_news and atrium_pages, which respectively add news publishing and usual static pages to our new portal.

So let's have now a closer look at the heart of this feature, the atrium_portal Spaces preset;

<?php
/**
* Implementation of hook_spaces_presets().
*/
function atrium_portal_spaces_presets() {
 
$export = array();
 
$spaces_presets = new stdClass;
 
$spaces_presets->disabled = FALSE;
 
$spaces_presets->api_version = 3;
 
$spaces_presets->name = 'atrium_portal';
 
$spaces_presets->title = 'Portal group';
 
$spaces_presets->description = 'Turn a group into a public portal. All users may view public content from this group. Users must request to join this group.';
 
$spaces_presets->space_type = 'og';
 
$spaces_presets->value = array(
   
'variable' => array(
     
'spaces_og_selective' => '1',
     
'spaces_og_register' => 0,
     
'spaces_og_directory' => 0,
     
'spaces_og_private' => 0,
     
'spaces_features' => array(
       
'atrium_blog' => '0',
       
'atrium_book' => '0',
       
'atrium_calendar' => '1',
       
'atrium_casetracker' => '0',
       
'atrium_members' => '1',
       
'atrium_news' => '1',
       
'atrium_pages' => '1',
       
'atrium_shoutbox' => '0',
       
'spaces_dashboard' => '1',
      ),
     
'spaces_setting_home' => 'dashboard',
     
'site_frontpage' => 'dashboard',
     
'menu_primary_links_source' => 'menu-portal',
     
'menu_default_node_menu' => 'menu-portal',
     
'designkit_color' => array(
       
'background' => '#3399aa',
      ),
     
'designkit_image' => array(
       
'logo' => 0,
      ),
    ),
   
'context' => array(
     
'spaces_dashboard-custom-1:reaction:block' => array(
       
'blocks' => array(
         
'views-atrium_news-block_3' => array(
           
'module' => 'views',
           
'delta' => 'atrium_news-block_3',
           
'region' => 'content',
           
'weight' => 0,
          ),
         
'views-calendar_listing-block_1' => array(
           
'module' => 'views',
           
'delta' => 'calendar_listing-block_1',
           
'region' => 'right',
           
'weight' => 0,
          ),
        ),
      ),
     
'spaces_dashboard-custom-2:reaction:block' => array(
       
'blocks' => array(),
      ),
     
'spaces_dashboard-custom-3:reaction:block' => array(
       
'blocks' => array(),
      ),
     
'spaces_dashboard-custom-4:reaction:block' => array(
       
'blocks' => array(),
      ),
     
'spaces_dashboard-custom-5:reaction:block' => array(
       
'blocks' => array(),
      ),
    ),
  );

 
// Translatables
  // Included for use with string extractors like potx.
 
t('Portal group');
 
t('Turn a group into a public portal. All users may view public content from this group. Users must request to join this group.');

 
$export['atrium_portal'] = $spaces_presets;
  return
$export;
}
?>

The first important customization is the set of features we are enabling for our new Portal preset. Since the set of features available to each group is stored into the spaces_features variable the Spaces module can override its value when we are browsing a Portal group. Here what we have enabled:

<?php
...
'spaces_features' => array(
 
'atrium_blog' => '0',
 
'atrium_book' => '0',
 
'atrium_calendar' => '1',
 
'atrium_casetracker' => '0',
 
'atrium_members' => '0',
 
'atrium_news' => '1',
 
'atrium_pages' => '1',
 
'atrium_shoutbox' => '0',
 
'spaces_dashboard' => '1',
),
...
?>

This is generally true with all those settings that are stored into variables, like default theme, primary links menu, default user picture, etc...

With a space preset we can also override the default block settings of the Open Atrium dashbaord. For example, for our Portal we want to show a news block on the content region and a calendar with the latest events on the right sidebar region. Here is how to do that:

<?php

...
'context' => array(
 
'spaces_dashboard-custom-1:reaction:block' => array(
   
'blocks' => array(
     
'views-atrium_news-block_3' => array(
       
'module' => 'views',
       
'delta' => 'atrium_news-block_3',
       
'region' => 'content',
       
'weight' => 0,
      ),
     
'views-calendar_listing-block_1' => array(
       
'module' => 'views',
       
'delta' => 'calendar_listing-block_1',
       
'region' => 'right',
       
'weight' => 0,
      ),
    ),
  ),
...
?>

With this simple space preset we can actually turn an Open Atrium group into a real public portal for our organization.

A different way to look at Open Atrium

A stable code-driven customization joint to the powerful Spaces module could push Open Atrium much far behind its original private-intranet. This great distribution, in fact, can be seen as a versatile platform that can answer to the most diverse needs of an organization providing, for example, groups that can be turn into full featured public portals or used to organize events, etc... With the right customization each group could also be heavily customizable, letting the administrator to completely change their look and feel to serve the most different purposes.

If you are interested in learning more about the topic covered in this blog post you can check out our Drupal Con Chicago 2011 session proposal here.

Comments

Comments

Anonymous
18 Dec 2010

Its really cool!

Its really cool!

Anonymous, 18 Dec 2010

Its really cool!

Anonymous, 18 Dec 2010
nenne
20 Dec 2010

Hello, thanks for a really cool and useful post. Do you have any idea on how one would make a feature global? Say you want a global shoutbox that is visible outside all groups and inside all groups.

Thanks again for an awesome post!

Hello, thanks for a really cool and useful post. Do you have any idea on how one would make a feature global? Say you want a global shoutbox that is visible outside all groups and inside all groups.

Thanks again for an awesome post!

nenne, 20 Dec 2010

Hello, thanks for a really cool and useful post. Do you have any idea on how one would make a feature global? Say you want a global shoutbox that is visible outside all groups and inside all groups.

Thanks again for an awesome post!

nenne, 20 Dec 2010
cmacao
28 Dec 2010

A really helpful document, thank you very much.

A really helpful document, thank you very much.

cmacao, 28 Dec 2010

A really helpful document, thank you very much.

cmacao, 28 Dec 2010
Daniel Beilinson
3 Jan 2011

Cool stuff. But as I see you create "portal" menu for all portal groups. That isn't cool. It'll be extraordinary If I could chose menu for portal group when I create it. Because in this case I can create many different portals in one site. But only one menu for all portal groups - that's big limitation.

Cool stuff. But as I see you create "portal" menu for all portal groups. That isn't cool. It'll be extraordinary If I could chose menu for portal group when I create it. Because in this case I can create many different portals in one site. But only one menu for all portal groups - that's big limitation.

Daniel Beilinson, 3 Jan 2011

Cool stuff. But as I see you create "portal" menu for all portal groups. That isn't cool. It'll be extraordinary If I could chose menu for portal group when I create it. Because in this case I can create many different portals in one site. But only one menu for all portal groups - that's big limitation.

Daniel Beilinson, 3 Jan 2011
Antonio De Marco
5 Jan 2011

Even though there is only one portal menu for the entire Open Atrium installation page nodes will appear only in groups where they belong, as for menu items (but only after implementing hook_db_rewrite_sql()). Each group will then display only its own portal menu "slice".

A cleaner solution could be probably implemented by integrating OG Menu module (http://drupal.org/project/og_menu).

Even though there is only one portal menu for the entire Open Atrium installation page nodes will appear only in groups where they belong, as for menu items (but only after implementing hook_db_rewrite_sql()). Each group will then display only its own portal menu "slice".

A cleaner solution could be probably implemented by integrating OG Menu module (http://drupal.org/project/og_menu).

Antonio De Marco, 5 Jan 2011

Even though there is only one portal menu for the entire Open Atrium installation page nodes will appear only in groups where they belong, as for menu items (but only after implementing hook_db_rewrite_sql()). Each group will then display only its own portal menu "slice".

A cleaner solution could be probably implemented by integrating OG Menu module (http://drupal.org/project/og_menu).

Antonio De Marco, 5 Jan 2011
dalin
3 Jan 2011

As someone who has worked with Drupal for 6 years I find Features to be incredibly obtuse. There's got to be a better way.

As someone who has worked with Drupal for 6 years I find Features to be incredibly obtuse. There's got to be a better way.

dalin, 3 Jan 2011

As someone who has worked with Drupal for 6 years I find Features to be incredibly obtuse. There's got to be a better way.

dalin, 3 Jan 2011
Andrea Pescetti
5 Jan 2011

Ultimately, the best solution will indeed depend on your needs. We find Features to be the best tool for our needs (distributed development, clean change tracking, easy packaging of template sites); it does have limitations, such as handling "staging" content, but it is a major improvement over a standard Drupal workflow.

Ultimately, the best solution will indeed depend on your needs. We find Features to be the best tool for our needs (distributed development, clean change tracking, easy packaging of template sites); it does have limitations, such as handling "staging" content, but it is a major improvement over a standard Drupal workflow.

Andrea Pescetti, 5 Jan 2011

Ultimately, the best solution will indeed depend on your needs. We find Features to be the best tool for our needs (distributed development, clean change tracking, easy packaging of template sites); it does have limitations, such as handling "staging" content, but it is a major improvement over a standard Drupal workflow.

Andrea Pescetti, 5 Jan 2011
Anonymous
5 Feb 2011

I'm very interested in the part about creating a "Portal" group type, but I am very new to Drupal and don't quite understand how you would go about creating this based on the steps you listed. Do you think you could create a slightly more detailed step-by-step procedure for doing this?

I'm very interested in the part about creating a "Portal" group type, but I am very new to Drupal and don't quite understand how you would go about creating this based on the steps you listed. Do you think you could create a slightly more detailed step-by-step procedure for doing this?

Anonymous, 5 Feb 2011

I'm very interested in the part about creating a "Portal" group type, but I am very new to Drupal and don't quite understand how you would go about creating this based on the steps you listed. Do you think you could create a slightly more detailed step-by-step procedure for doing this?

Anonymous, 5 Feb 2011
Andrea Pescetti
7 Feb 2011

We just posted here the presentation we gave yesterday at Drupal Dev Days Brussels about this topic: http://nuvole.org/node/32

Video was not recorded, unfortunately; if slides are not explanatory enough for you, just be patient, we are going to post more descriptive step-by-step examples in the next weeks!

We just posted here the presentation we gave yesterday at Drupal Dev Days Brussels about this topic: http://nuvole.org/node/32

Video was not recorded, unfortunately; if slides are not explanatory enough for you, just be patient, we are going to post more descriptive step-by-step examples in the next weeks!

Andrea Pescetti, 7 Feb 2011

We just posted here the presentation we gave yesterday at Drupal Dev Days Brussels about this topic: http://nuvole.org/node/32

Video was not recorded, unfortunately; if slides are not explanatory enough for you, just be patient, we are going to post more descriptive step-by-step examples in the next weeks!

Andrea Pescetti, 7 Feb 2011
Lu
6 May 2011

Dear Antonio,

I am having some difficulties understand some concepts explained in this blog, i have created a clone of a public group and followed similar steps as above, but i don't understand (or know how) turn this feature in a "public website".

I'm assuming you need to create a public group, override whatever you want, and then make it your frontpage?

How does OA handle the frontpage, is it a public group by default?

What i am trying to achieve is to have a "public website" for the front page, but "controlled groups" for the rest of the site. The main issue i'm facing is that the homepage inherits all the features menu and i'm not sure where to override it. I can easily override it in my custom controlled groups.

Please help me! I've spent so many days banging my head against the wall, i'm hoping you can point me in the right direction.

Thank you, Lu

Dear Antonio,

I am having some difficulties understand some concepts explained in this blog, i have created a clone of a public group and followed similar steps as above, but i don't understand (or know how) turn this feature in a "public website".

I'm assuming you need to create a public group, override whatever you want, and then make it your frontpage?

How does OA handle the frontpage, is it a public group by default?

What i am trying to achieve is to have a "public website" for the front page, but "controlled groups" for the rest of the site. The main issue i'm facing is that the homepage inherits all the features menu and i'm not sure where to override it. I can easily override it in my custom controlled groups.

Please help me! I've spent so many days banging my head against the wall, i'm hoping you can point me in the right direction.

Thank you, Lu

Lu, 6 May 2011

Dear Antonio,

I am having some difficulties understand some concepts explained in this blog, i have created a clone of a public group and followed similar steps as above, but i don't understand (or know how) turn this feature in a "public website".

I'm assuming you need to create a public group, override whatever you want, and then make it your frontpage?

How does OA handle the frontpage, is it a public group by default?

What i am trying to achieve is to have a "public website" for the front page, but "controlled groups" for the rest of the site. The main issue i'm facing is that the homepage inherits all the features menu and i'm not sure where to override it. I can easily override it in my custom controlled groups.

Please help me! I've spent so many days banging my head against the wall, i'm hoping you can point me in the right direction.

Thank you, Lu

Lu, 6 May 2011
Ryan Yu
13 May 2011

Dear Antonio,

Thanks a lot for your awesome document.

There's one question I would really like to do. Spent whole day but couldn't find any solution. If you have any ideas, would you please share your ideas?

My question is... Is there any way I can disable/hide the "All cases" menu on Case Tracker?

I only want to display My cases, Projects, Archived, but not All cases...

Thank you heaps in advance!

Dear Antonio,

Thanks a lot for your awesome document.

There's one question I would really like to do. Spent whole day but couldn't find any solution. If you have any ideas, would you please share your ideas?

My question is... Is there any way I can disable/hide the "All cases" menu on Case Tracker?

I only want to display My cases, Projects, Archived, but not All cases...

Thank you heaps in advance!

Ryan Yu, 13 May 2011

Dear Antonio,

Thanks a lot for your awesome document.

There's one question I would really like to do. Spent whole day but couldn't find any solution. If you have any ideas, would you please share your ideas?

My question is... Is there any way I can disable/hide the "All cases" menu on Case Tracker?

I only want to display My cases, Projects, Archived, but not All cases...

Thank you heaps in advance!

Ryan Yu, 13 May 2011
30 May 2011

We can't give support on specific issues, but our session from the Alpine DrupalCamp Bressanone/Brixen 2011 (slides are in English, video in English will be published soon) may give you some more hints: http://www.alpinedrupalcamp.org/sessions/personalizzazione-avanzata-di-o...

We can't give support on specific issues, but our session from the Alpine DrupalCamp Bressanone/Brixen 2011 (slides are in English, video in English will be published soon) may give you some more hints: http://www.alpinedrupalcamp.org/sessions/personalizzazione-avanzata-di-o...

, 30 May 2011

We can't give support on specific issues, but our session from the Alpine DrupalCamp Bressanone/Brixen 2011 (slides are in English, video in English will be published soon) may give you some more hints: http://www.alpinedrupalcamp.org/sessions/personalizzazione-avanzata-di-o...

, 30 May 2011
raduen
30 Jun 2011

Where do i put the code to replace the "Welcome" video with the "Latest discussion" block? Must i put this in a file of module ? if it's a module how do i do that? I'm verry new to this (1 day).

Thanks

Where do i put the code to replace the "Welcome" video with the "Latest discussion" block? Must i put this in a file of module ? if it's a module how do i do that? I'm verry new to this (1 day).

Thanks

raduen, 30 Jun 2011

Where do i put the code to replace the "Welcome" video with the "Latest discussion" block? Must i put this in a file of module ? if it's a module how do i do that? I'm verry new to this (1 day).

Thanks

raduen, 30 Jun 2011
Andrea Pescetti
10 Jul 2011

You will need to be familiar with a Features based development workflow. Read documentation on http://drupal.org/project/features or the "code-driven development" posts on this blog or find online how to use and customize Features.

You will need to be familiar with a Features based development workflow. Read documentation on http://drupal.org/project/features or the "code-driven development" posts on this blog or find online how to use and customize Features.

Andrea Pescetti, 10 Jul 2011

You will need to be familiar with a Features based development workflow. Read documentation on http://drupal.org/project/features or the "code-driven development" posts on this blog or find online how to use and customize Features.

Andrea Pescetti, 10 Jul 2011
Andrea Pescetti
4 Nov 2011

Comments are closed. Please contact us through the contact form on this site if you need development on Open Atrium or if you are interested in our trainings.

Comments are closed. Please contact us through the contact form on this site if you need development on Open Atrium or if you are interested in our trainings.

Andrea Pescetti, 4 Nov 2011

Comments are closed. Please contact us through the contact form on this site if you need development on Open Atrium or if you are interested in our trainings.

Andrea Pescetti, 4 Nov 2011

Get your project started today!

Contact us