Advanced Open Atrium customization
Advanced Open Atrium customization
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:
- How to add custom user profile fields;
- How to override Atrium's core configuration;
- 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
Its really cool!
Its really cool!
Its really cool!
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!
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!
A really helpful document, thank you very much.
A really helpful document, thank you very much.
A really helpful document, thank you very much.
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.
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.
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).
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).
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.
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.
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.
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.
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?
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?
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!
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!
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
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,
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!
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!
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...
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...
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
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
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.
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.
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.
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.