Jun 13 2019
Jun 13

CMI 2.0 session at Drupaldevdays in Cluj-Napoca

Fabian Bircher

13 Jun 2019

0 Comments

Fabian Bircher

13 Jun 2019

0 Comments

Fabian Bircher, 13 Jun 2019 - 0 Comments

Session slides for the dev days CMI 2.0 session

Today I presented the CMI 2.0 updates at the drupal dev days in Cluj-Napoca. The session went well and I received good feedback and had interesting conversations about configuration management after it.

Attached are the slides I presented.

There are plenty of issues to work on, join us in the sprint room or on the #config drupal slack. Find more information on the CMI 2 project page and issues tagged with CMI 2.0 candiate

CMI 2.0 Devdays 2019.pdf (932.61 KB)Download
Apr 09 2019
Apr 09

CMI 2.0 at Drupalcon Seattle 2019

Fabian Bircher

9 Apr 2019

1 Comment

Fabian Bircher

9 Apr 2019

1 Comment

Fabian Bircher, 9 Apr 2019 - 1 Comment

Help us answer difficult questions about configuration management for Drupal core.

Tomorrow Wednesday at 13:45 (Pacific Daylight Time) in room 6C we have the CMI 2.0 updates session at the Drupalcon.

Together with Mike Potter, we will briefly present the work that has been done so far and lay out the road map for what is to come. The session will be recorded and the slides are attached to this post (subject to change).

I will not go more into details of the session in this post but I would like to mention a challenge for which we need to find a solution and I would like everyone to invite to join the discussion on drupal.org #3046903 or here in the comments.

The challenge is how to deal with update hooks that change configuration which run only in certain environments and thus make the configuration deployment more difficult.

CMI 2.0 DC Seattle 2019.pdf (1.28 MB)Download
Mar 06 2019
Mar 06

Help us set the stage for future configuration management improvements in core.

The configuration management initiative 2.0 needs your help.

I will be presenting updates of CMI 2.0 at the upcoming Drupalcon Seattle together with Mike Potter.

Some of the highlights of the CMI 2.0 road map for inclusion in Drupal core are an improved version of the concept of Config Filter (in the form of the config storage transformation api) and a simplified version of Config Split (in the form of config environments).
Unfortunately those big things will not make it into 8.7, but we could lay the ground work for 8.8.

But the deadline for some patches for Drupal 8.7 is this Friday!

It would be great if you could help us get the following issues to RTBC and committed:

#3036193: Add ExportStorageFactory to allow config export in third party tools
This would allow us to add a service to core that drush, drupal console and other tools and modules can use to export configuration. If this lands in 8.7 we will be able to patch Drush and Drupal Console between 8.7 and 8.8 and make improvements to configuration management such as adding a Config Environment module to core without then patching the cli tools again afterwards.

#3016429: Add a config storage copy utility trait
This adds a new utility trait that would make dealing with configuration storages easier. Currently there are a bunch of modules that implement this logic by themselves and not all of them do it correctly. This lead to bugs in Drush and Drupal Console and even Drupal core has a bug (which is fixed by this issue).

Thanks already in advance.

PS: If you are interested in more CMI 2.0 issues to review or work on check the CMI 2.0 candidate issue tag.

Apr 09 2018
Apr 09

A new workflow for distribution configuration management.

Drupal core workflow limitations

It is not a secret that the configuration management in Drupal 8 core was made for only one specific use case: move configuration from one environment to another for the same site. Everything else was left for contrib to find solutions for. Config Installer is necessary to set up a site starting from existing configuration and Config Split is needed to have environment specific configuration that go beyond simple configuration overrides, like development modules enabled only locally. But the whole workflow still assumes that developers - most often in the same team - have control over the environments and deployment of the site.

Distributions are not covered

Distributions are very different. When maintaining a distribution one doesn't develop a specific site but rather the template to build different sites with. Deploying configuration as we do it for a single site does not have any meaning because there is no one production site to deploy to. Each site based off a distribution is its own site with its own site uuid and its own possible customisations and possibly its own development and production environments. At the same time as a consumer of a distribution - a site owner of a site based off a distribution - one wants to update the distributions features while keeping the customisations.

Update hooks?

Different distributions handle this in different ways. A first approach to solve this issue is treating it the same way you would a schema update and change the configuration on a site with an update hook. The problem with this is that update hooks are meant to fix the database to be able to run with the version of code that is in use on the site. The first thing one needs to do after updating the code base is to run the update hooks to realign the database. Configuration management has different needs and when updating the configuration in an update hooks means that one has to be careful to check that the configuration is in the expected state. And the only recourse is to log and make sure the user is informed what manual actions he needs to do to update the configuration himself. As there is no place to involve the user with a choice while update hooks are run.

We propose a new kind of workflow, in essence it allows developers of a distribution to say how the "distributions configuration" is supposed to be updated and it allows site owners of a site based on a distribution to treat the distribution maintainers as a developer on their team. At the same time this does not interfere with the configuration management workflow for staging and deploying configuration to the production site.

The primary function of Config Distro is to allow updating a distributions configuration in a new workflow and give the site owners more control and insight on how the configuration of their site changes. It is a new way to imagine the configuration management system in a way that lets sites own their configuration but allowing distributions to provide updated configuration for existing sites.

A new dimension

In a blog post one year ago I talked about different dimensions of configuration management;

  • vertical: moving configuration between environments but for the same site
  • horizontal: moving configuration between different sites. for example for distribution updates.

Config Distro is a UI and a drush command for that workflow. It is intended to be used by site builders who base their site on a distribution and want to import configuration updates from the updated distribution. The UI is essentially a parallel to configuration import screen for the workflow supported by core. But instead of importing the configuration from the files used to move/deploy configuration between environments you import from a special configuration storage which starts out with the sites active configuration and has the distributions updates applied to it. This means you do not have problems with mismatched site uuids or things being removed that you added and were not part of the distribution. And updates can apply (or not) to translations even if the distribution did not have languages.

Where do updates come from

If you only install Config Distro, the import screen eternally shows that there is nothing to import. This is because the module only provides the framework for this to work, ie the UI and the drush command. The module is not opinionated on how or what should be updated. All the complexity can be addressed by a distribution maintainer with the help of a ConfigFilter plugin (the same way Config Split and Config Ignore work). One such module is Config Sync. All the complexity of finding out what what configuration a module has originally shipped with, what it does now and whether a user has changed the originally installed configuration is left to Config Sync and its dependencies.

Choice

Just like Config Ignore allows you to opt out of some of the configuration management workflows, Config Distro has a Config Distro Ignore module that lets you retain certain configuration from being changed when you hit the "import" button. The "Retain configuration" button is available right next to the "View differences" button.

Config Distro overview

Clicking it leads to a form that lets you choose to retain the configuration permanently or only for this specific update. It also allows you to ignore a update for a specific language.

Config Distro detail

Example

In our team we set up a site based on a distribution. We added our own login module for our single sign on and added a few webforms. Now there is a new version of the distribution with some new features and I would like upgrade the site to using the new features. I am tasked with updating the site, here is what I do:

  • I update the code of the distribution by specifying the new version in composer.json and do a composer update to get the updated code*
  • I run the database updates drush updb to align the database with the code*
  • I go to the distro update screen provided by Config Distro
    • This screen looks very familar, it looks the same way as when I import configuration changes my team mates made after I get their code with git pull.
    • I see a new module is going to be installed and a few views and settings from the distribution are updated.
    • Our webforms are not going to be removed and our custom modules not uninstalled.
  • I click "import all"
  • Now my site has the updated code and configuration so I export the configuration for deployment: drush cex and commit*
  • My colleges get the update the same way they get normal changes that happen during development*:
    • git pull get the code
    • composer install get the external code (vendor, contrib, etc)
    • drush updb align the database with the new code base.
    • drush cim import the sync configuration.

* This is the same procedure as for any module update on any site.
Distributions may add a "Auto upgrade" setting and then import the Config Distro in a post_update_hook to bypass the manual step required of site administrators upgrading the distribution.

Conclusion

Config Distro provides a new workflow for updating distributions with a familiar feel. It recognizes that update hooks are not an adequate solution for updating a sites configuration when a site owns the configuration and site administrators may have changed the initially provided configuration.
It allows developers of distributions to alter the sites configuration through ConfigFilter plugins and it gives site administrators a choice of what to import.
Config Distro is just the framework for extending cores configuration management to allow managing configuration changes to get into the site from a third party such as the distribution maintainers. It does not interfere with the traditional workflow and importing the configuration updates from a distribution should be seen as any other configuration change such as adding a new view or changing permissions: You go to an admin page and you click some things in a form, then you export the configuration and deploy it.

Future - CMI 2.0

While it already works, Config Distro is still in an alpha state. Config Distro is part of a larger effort to improve the configuration management in Drupal. You can find further information and participate in the discussion on drupal.org

Oct 13 2017
Oct 13

Config Split treats all the cli the same.

Drupal 8.4 and its upgrade to Symfony 3 has made the compatibility of the global Drush 8 a bit more challenging. Drush 9 works with Drupal 8.4 but it is not stable yet and the format of how third party Drush commands are made has changed significantly.

While Drush 9 comes with a command that helps porting Drush 8 commands you will still end up maintaining very similar code in two places one with calls to drush_confirm('...') and one with $this->io()->confirm('...'). If you decide to also provide your commands for Drupal console you now have three times the burden.

Because we tried to provide the commands for Config Split for both Drush and Drupal console early on we faced this problem already more than a year ago. And now it has paid off because porting the commands to Drush 9 was very quick.

The solution is actually really simple and brings the added benefit of being able to test the business logic of the commands in the absence of Drush or Drupal console. It is all about separating the command discovery from the command logic. Drush 8, 9 and Drupal console all have a bit different ways to discover and invoke commands, but the business logic you want to implement is the same so all we have to do is to extract a common "interface" our custom service can implement and then make the command definitions wrap that and keep things DRY.

The CliService

Config Split defines a config_split.cli service with the class ConfigSplitCliService with all its dependencies injected. It has the methods \Drupal\config_split\ConfigSplitCliService::ioExport and \Drupal\config_split\ConfigSplitCliService::ioImport that implement all the commands logic and delegate the actual importing and exporting to specific methods.

The method signature for both the export and import method are more or less the same: CliService::ioMethod($arguments, $io, callable $t).

  • $arguments: The arguments passed to the command.
  • $io: This is an object that interacts with the command line, in Drush 9 and Drupal console this comes from the Symfony console component, for Drush 8 we created a custom wrapper around drush_confirm and drush_log called ConfigSplitDrush8Io.
  • $t: This is essentially a t function akin to how Drupal translates strings. Because Drupal console translates things differently we had to be a bit creative with that by adding a t method to the command.

Commands wrap the service

The Drush 8 command is essentially:

<?php
function drush_config_split_export($split = NULL) {
 
// Make the magic happen.
 
\Drupal::service('config_split.cli')->ioExport($split, new ConfigSplitDrush8Io(), 'dt');
}
?>

For Drush 9 we can use dependency injection and the Drush 9 command becomes essentially:

<?php
class ConfigSplitCommands extends DrushCommands {
  public function
splitExport($split = NULL) {
   
$this->cliService->ioExport($split, $this->io(), 'dt');
  }
}
?>

And very similar the Drupal console command:

<?php
class ExportCommand extends SplitCommandBase {
  protected function
execute(InputInterface $input, OutputInterface $output) {
   
$this->setupIo($input, $output);
   
// Make the magic happen.
   
$this->cliService->ioExport($input->getOption('split'), $this->getIo(), [$this, 't']);
  }
}
?>

Testing

The ConfigSplitCliServiceTest is a KernelTest which asserts that the export works as expected by exporting to a virtual file system. The test coverage is not 100% (patches welcome) but the most important aspects for the complete and conditional splitting (blacklist/graylist) is thoroughly tested. There are no limitations on what or how you can test your CliService since it is self contained in your module and does not depend on Drush or the Drupal console. For example one could write a unit test with a mocked $io object that asserts that the messages printed to the cli are correct.

Aug 21 2017
Aug 21

Stable release for Config Split and Config Filter

Fabian Bircher

21 Aug 2017

1 Comment

Fabian Bircher

21 Aug 2017

1 Comment

Fabian Bircher, 21 Aug 2017 - 1 Comment

Celebrating the 8.x-1.0 release of our configuration management helper modules.

One year ago we released the first public version of Config Split with the goal to simplify working with Drupal cores configuration management. The main motivation was to find a solution for having development modules in local environments and avoiding to deploy their configuration. To achieve this in the cleanest way possible we decided to interact with Drupal only during the configuration import and export operations by altering what is read from and written to the \Drupal\Core\Config\StorageInterface.

We quickly realized that this is a powerful way to interact with how Drupal sees the configuration to import and so we split off the code that does the heavy lifting into its own module and now Config Ignore and Config Role Split use the same mechanism to do their thing.

Config Split now has documentation pages you are welcome to contribute to and there will be a session at DrupalCon in Vienna in which I will show how it can be used to manage a sites configuration in interesting ways.

If you were an early adopter (pre beta3) but have not updated to a recent version, you will need to install Config Filter first or patch core. The workaround and legacy code has now been removed and the current code is going to be backwards compatible in the future. So if you use the APC class loader, make sure to clear the apc/apcu cache or you might get an error after updating.

Apr 25 2017
Apr 25

Key points from our configuration management sessions.

Unfortunately none of us from Nuvole are attending DrupalCon Baltimore and can’t, therefore, attend the “hallway track” and join discussions in person. We have held presentations about advanced configuration management in Drupal 8 at all Drupal events we attended in the last year including the last DrupalCon in Dublin. So I’ll try to cover some concepts here that could help the discussion about how the configuration management can be improved.

To me there are at least two important dimensions to configuration management in Drupal 8 and different contrib project have sprouted to address:

Vertical: transfer configuration between different environments of the same site.
Horizontal: transfer configuration between different sites.

Following are a few contrib solutions and core issues that address the different itches. This is not meant to be an exhaustive or definitive list but highlight the different problem spaces. Many more contrib solutions address some issues in this space to accommodate various different workflows.

Vertical

Drupal 8 core only addresses this use case, however, there are some important cases not covered (yet). The management of configuration between the different environments is best taken care of by importing and exporting the whole sites configuration together.

Installing from existing configuration:

Contrib solution: Config installer
Core issues: Allow a site to be installed from existing configuration, Allow a profile to be installed from existing config

Environment specific configuration (ie devel only on develop)

Contrib solution: Config Split
Core issues: Allow exported configuration to be environment-specific, Allow development modules to opt out of config-export

Configuration with Content

Contrib solution: Default Content, Deploy

Horizontal

Due to the fact that the same tools can be used for both dimensions and the fact that in Drupal 7 features was abused for doing the vertical configuration management as well this concept may not be so clear. Ideally configuration between sites is shared from the development environment of one site to the development environment of another, and the vertical tools with drupal core are used for deployment. Moving configuration between different sites is done by moving a subset of configuration between environments.

Re-using a set of configuration in another site

Contrib Solution: Features
There are many more modules designed to deal with distributions and dealing with the paradigm that sites now own the configuration.

Inheriting installation profiles

Core issue: Allow profiles to provide a base/parent profile

Multisite with large portion of shared configuration

Contrib Solution: Config Split
While this is not the original problem it tries to solve, it is reported to be used for it..

Conclusion

I may have an obvious bias towards config split since we maintain that module but it is just one of many config related modules. I hope there is a fruitful discussion in Baltimore about configuration management in Drupal 8. BoF

Related blog posts:

Mar 30 2017
Mar 30

Our presentations at Drupal Dev Days Seville

Andrea Pescetti

30 Mar 2017

2 Comments

Andrea Pescetti

30 Mar 2017

2 Comments

Andrea Pescetti, 30 Mar 2017 - 2 Comments

New directions for Config Split and UI Patterns

Last week we attended and sponsored the Drupal Developer Days in Seville where we also had two well attended sessions. Introducing the UI Patterns module: use atomic UI components everywhere in Drupal 8 and Advanced Configuration Management with Config Split et al. attached here are the promised slides, as well as a few updates about the modules.

What's new in Config Split

Drush

As we posted about before, drush supports the Config Split workflow since 8.1.10. In the next version drush will drop the support for its --skip-modules flag and people using it should upgrade to using Config Split.

Split Storage in Database

Previous versions of Config Split allowed to set an empty split folder which resulted in the configuration to be lost. To avoid saving the configuration into files under version control one would therefore have to set up a temporary directory and save the split there. But with the last development release a separate database storage is used when not specifying a split folder. This allows configuration to be "stashed" in the database for a deployment. A specific export first is still and will always be necessary by design.

What's new in UI Patterns

Following a productive BOF meeting at DDD, it was decided to move everything that concerns defining and displaying patterns locally into a separate module.

This will allow for a better and more solid architecture: the main UI Patterns module will be solely responsible to provide plugins and other glue code: it will then be responsibility of modules implementing component library integrations to expose their components using pattern derivers.

Discussion is ongoing at https://github.com/nuvoleweb/ui_patterns/issues/86 and more generic future plans are being dicussed at https://github.com/nuvoleweb/ui_patterns/issues/76

presentation-ui_patterns.pdf (3.36 MB)Download presentation-config_split.pdf (802.59 KB)Download
Feb 27 2017
Feb 27

Our solution for advanced configuration management workflows has just become more powerful! The core of what makes Configuration Split work so nicely with drush and the Drupal UI has been split off in a new module: Config Filter! Config Filter exposes a ConfigFilter plugin and swaps the sync storage applying all the active ConfigFilters to it. This means it is no longer necessary to manually swap the service as we recommended to do in the past and it works also when installing a site, as the swapping happens only when the module is installed. As of drush 8.1.10 this works with the default config import and export commands.

Update Config Split

For current users of the Config Split module it means that they should remove the custom service swapping as part of the update and then apply the database updates which will install Config Filter (you already downloaded it with composer update, right?).

New command-line options and new workflows

With the re-factoring we also changed the options of the drush and console commands. We added a new option for specifying a split and then export to and import from only that split directory; this supersedes the previous options to specify separate export destinations and import sources - they are not needed for the simple work flow we advocate for, and the behaviour can easily be achieved by modifying settings.php as needed.

With the addition of the single split export, a new workflow becomes possible: export only the "production" split, before importing the whole configuration which will have it merged back in.

Improved Graylists

In addition to the new architecture the graylist feature has been improved so that dependencies can be graylisted as well and optionally only items that differ from the sync storage are split off. More details and more documentation will come in future.

Roadmap

The ultimate goal is to improve the export API in Drupal 8 core so that more advanced workflows are possible. Config Filter is our proposal for a solution in contrib, but we feel that this functionality should belong to Core.

On the way to Core, here are some more immediate steps:

  • Clean up after the big refactoring, adding automated tests for some special cases.
  • Improve the documentation.
  • Integrate with Config Readonly to allow locking the site except for the configuration defined in splits.
  • For those that want to do configuration management without seatbelts, integrate Config Ignore with Config Filter so that it can work smoothly next to Config Split.
  • ...and eventually propose Config Filter for inclusion in Core!

More information and acknowledgments

The re-factoring started during the Drupal Mountain Camp in Davos and I would like to thank the organizing committee for the great event. On Friday I gave a presentation about my favorite topic in Drupal: Configuration Management, attached here are the slides based on the Nuvole presentation at DrupalCon Dublin 2016.

For any further information see the module pages for Config Split and Config Filter and their issue queues.

Jan 23 2017
Jan 23

Expose atomic UI patterns as plugins and use them as drop-in templates in your Drupal 8 projects

Update: We have setup a Gitter chat room if you have any specific questions about the module's functionality: Gitter

Establishing an atomic design system in your project is one of the most effective way to build a consistent and maintainable user interface.

Over the past years projects like PatternLab or the Component Libraries module aimed at lowering the cost of maintaining (PatternLab) and re-using (Component Libraries) UI patterns in your projects, be it a generic PHP application or a brand new Drupal 8 site.

But, as we all know, when it comes to presenting content the Drupal 8 landscape is quite diverse: you can layout your pages using Panels or Views, style your entities using Display Suite view modes, group your fields with Field group, etc.

Such a diversification can surely present some challenges when it comes at reusing a well-designed and consistent UI library. In other words: how can I transparently use the same UI pattern in my views, layouts, field formatters, etc.?

Enter the UI Patterns module

The UI Patterns module allows you to define and expose self-contained UI patterns as Drupal 8 plugins and use them seamlessly as drop-in templates for panels, field groups, views, Display Suite view modes and field templates.

The module also generates a pattern library page that can be used as documentation for content editors or as a showcase for business and clients (the following example is styled using the Bootstrap theme):

The UI Patterns module also easily integrates with with tools like PatternLab or modules like Component Libraries.

Define your patterns

Patterns can be defined using YAML in files named MY_MODULE.ui_patterns.yml or MY_THEME.ui_patterns.yml using the following format:

blockquote:
  label: Blockquote
  description: Display a quote with attribution information.
  fields:
    quote:
      type: text
      label: Quote
      description: Quote text.
      preview: Life is like riding a bicycle. To keep your balance, you must keep moving.
    attribution:
      type: text
      label: Attribution
      description: Quote attribution.
      preview: Albert Einstein

After defining the pattern you have to provide a Twig template to render it which, in our case, could look like that:

<blockquote>
  <p>{{ quote }}</p>
  <footer>{{ attribution }}</footer>
</blockquote>

Once you are done you can visit the pattern library page and check your new Blockquote pattern in action:

We have much more options available to make sure pattern definition can fit your use case (i.e. template overrides, etc.), make sure you check the documentation for the full list.

Use your patterns everywhere

After exposing your patterns you are ready to use them anywhere thanks to the sub-modules bundled within UI Patterns, namely:

Example: style links as call-to-action buttons

One of the most ordinary situation is styling a group of links as call-to-action buttons. This can be easily achieved using UI Patters.

Say we have defined the following Button pattern:

button:
label: Button
description: A simple button.
fields:
   title:
     type: text
     label: Label
     description: The button label
     preview: Submit
   url:
     type: text
     label: URL
     description: The button URL
     preview: http://example.com

On the entity display setting page we access the link field setting by clicking on the gear icon:

Then, after selecting the Pattern field template and the Button pattern, we map the link field columns to the pattern's fields defined above:

Each value of our multi-valued link field will be then formatted using the Button pattern, as shown below:

Conclusions

The UI Patterns module aims at integrating your pattern library with the most used Drupal 8 rendering systems. It also makes easy to use third-party tools such as PatternLab.

The project is currently under active maintenance, please file issues and/or support requests using this GitHub repository.

P.S. Special thanks to aleksip for getting the integration with PatternLab and the Component Libraries to work!

IMPORTANT UPDATE: If you are using version 8.x-1.0-beta2 make sure you read this change note for a safe upgrade to newer versions.

Nov 28 2016
Nov 28

Solving one of Drupal 8 core's development and deployment work-flow issues.

One of the nice things that happened during Drupal Ironcamp in Prague last week was the first beta release of the Configuration Split that I started developing a few months ago.

As explained in the previous blog post about Configuration Split, the typical use case of Configuration Split is to be able to maintain a "development" configuration and a "production" configuration, where some of the modules or settings you use in development are not copied to production upon configuration export/import.

A typical use case

We assume that you have a production and development version of the same site and that they are aligned.

Step 1: Enable anything you need in development and work normally

Enabled UI modules In the development environment we enable Devel and UI modules enabled and we can create new content types, add fields and do all things we like to do while developing a Drupal site. Some of this configuration work is meant to go to the production site and some (e.g., the fact that Devel is enabled and related configuration) is not. We thus need to split our configuration.

Step 2: Create a split definition

Basic Split settings Choose a name for your "local" configuration and select all the configuration you don't want to have on the live site (even though, if you wish, you can still share it with colleagues). This can include modules you would not want to be enabled or configuration that is for development only. The path here is a folder next to the normal config sync directory outside of the web root. In the example above, we are splitting out to a configuration set named "Development" the Devel, Fields UI, Views UI modules and the system.menu.devel configuration.

Step 3: Export your configuration with config_split

$ drush config-split-export

In the most basic use case we just replace config-export with config-split-export in our workflow. This exports the elements we selected above to ../config/dev and the rest (the configuration we want to deplay) to our "standard" configuration folder, in this case ../config/sync.

Step 4: Import the "clean" configuration in production

On all environments we use the configuration import of config_split:

$ drush config-split-import

So in our usual workflow we replace config-import with config-split-import

In order not to have different workflows for development and production we simply deactivate the split on production by overriding the configuration in settings.php on production: $config['config_split.config_split.development']['status'] = FALSE;

This will result in the split definition to be deactivated. Deactivated Split settings And consequently the import will have the configuration blacklisted in the split removed and development modules deactivated.

What's new in the beta version

The following features are new or changed in the beta release:

  • The drush command works and has some text to warn users to which directories configuration will be written to.
  • The drupal console command is disabled, but there is a patch/branch you can use or help to make it functional again.
  • Split entities now have a status and the default command only uses the active splits. Of course you can override that in settings.php as with almost all configuration.
  • You can switch out the default config.storage.sync service in your services.yml file so that the default configuration sync UI uses the split import. Details are in the README.txt file.

More information and acknowledgments

On Friday I gave a presentation about my favorite topic in Drupal: Configuration Management, attached here are the slides.

I wish to thank IronCamp participants and especially Swentel and mr.baileys who worked on patches, and I'd like to thank IronCamp organizers for a very well organized event where I met a lot of old and new friends. Swentel also took care of documenting more advanced use cases of Configuration Split on his blog.

For any further information see the module page and its issue queue.

Sep 27 2016
Sep 27

Configuration Management: Theory and Practice

Andrea Pescetti

27 Sep 2016

2 Comments

Andrea Pescetti

27 Sep 2016

2 Comments

Andrea Pescetti, 27 Sep 2016 - 2 Comments

Our presentation at DrupalCon Dublin 2016

Developers often want to use Configuration Management outside its intended use case. New workflows and practices have to be established.

We've just presented a gallery of problems and solutions at DrupalCon Dublin 2016.

The room was packed, and many people were denied admission for security reasons. For them, and for those who didn't manage to come to this DrupalCon, we are making the full presentation available here:

[embedded content]

Configuration-Management-Theory-and-Practice.pdf (2.41 MB)Download
Sep 19 2016
Sep 19

Make the most out of your Behat tests by using custom contexts, dependency injection and much more.

This post is an excerpt from the topics covered by our DrupalCon Dublin training: Drupal 8 Development - Workflows and Tools.

At Nuvole we consider writing good tests as a fundamental part of development and, when it comes to testing a complex site, there is nothing better than extensive behavioral tests using Behat. The benefits of such a choice are quite obvious:

  • Tests are very easy to write.
  • Behat scenarios serve as a solid communication mean between business and developers.

As a site grows in complexity, however, the default step definitions provided by the excellent Behat Drupal Extension might not be specific enough and you will quickly find yourself adding custom step to your FeatureContext or creating custom Behat contexts, as advocated by all official documentation.

This is all fine except that your boilerplate test code might soon start to grow into a non-reusable, non-tested bunch of code.

Enter Nuvole's Behat Drupal Extension.

Nuvole's Behat Drupal Extension

Nuvole's Behat Drupal Extension is built on the shoulders of the popular Behat Drupal Extension and it focuses on step re-usability and testability by allowing developers to:

  • Organize their code in services by providing a YAML service description file, pretty much like we all are used to do nowadays with Drupal 8.
  • Override default Drupal Behat Extension services with their own.
  • Benefit of many ready-to-use contexts that are provided by the extension out of the box.

Installation and setup

Install Nuvole's Behat Drupal Extension with Composer by running:

bash $ composer require nuvoleweb/drupal-behat

Setup the extension by following the Quick start section available on the original Behat Drupal Extension page, just use NuvoleWeb\Drupal\DrupalExtension instead of the native Drupal\DrupalExtension in your behat.yml as shown below:

default:
  suites:
    default:
      contexts:
        - Drupal\DrupalExtension\Context\DrupalContext
        - NuvoleWeb\Drupal\DrupalExtension\Context\DrupalContext
        ...
  extensions:
    Behat\MinkExtension:
      goutte: ~
      ...
    # Use "NuvoleWeb\Drupal\DrupalExtension" instead of "Drupal\DrupalExtension".
    NuvoleWeb\Drupal\DrupalExtension:
      api_driver: "drupal"
      ...
      services: "tests/my_services.yml"
      text:
        node_submit_label: "Save and publish"

"Service container"-aware Contexts

All contexts extending \NuvoleWeb\Drupal\DrupalExtension\Context\RawDrupalContext and \NuvoleWeb\Drupal\DrupalExtension\Context\RawMinkContext are provided with direct access to the current Behat service container. Developers can also define their own services by adding a YAML description file to their project and setting the services: parameter to point to its current location (as shown above).

The service description file can describe both custom services and override already defined services. For example, given a tests/my_services.yml containing:

services:
  your.own.namespace.hello_world:
    class: Your\Own\Namespace\HelloWorldService

Then all contexts extending \NW\D\DE\C\RawDrupalContext or \NW\D\DE\C\RawMinkContext will be able to access that service by just calling:

<?php
class TestContext extends RawDrupalContext { /**
   * Assert service.
   *
   * @Then I say hello
   */
 
public function assertHelloWorld() {
   
$this->getContainer()->get('your.own.namespace.hello_world')->sayHello();
  }

}

?>

The your.own.namespace.hello_world service class itself can be easily tested using PHPUnit. Also, since Behat uses Symfony's Service Container you can list services your service depends on as arguments so to remove any hardcoded dependency, following Dependency Injection best practices.

Override existing services

Say that, while working on your Drupal 7 project, you have defined a step that publishes a node given its content type and title and you want to use the same exact step on your Drupal 8 project, something like:

Given I publish the node of type "page" and title "My page title"

The problem here is that the actual API calls to load and save a node differs between Drupal 7 and Drupal 8.

The solution is to override the default Drupal core services specifying your own classes in your tests/my_services.yml:

parameters:
  # Overrides Nuvole's Drupal Extension Drupal 7 core class.
  drupal.driver.cores.7.class: Your\Own\Namespace\Driver\Cores\Drupal7
  # Overrides Nuvole's Drupal Extension Drupal 8 core class.
  drupal.driver.cores.8.class: Your\Own\Namespace\Driver\Cores\Drupal8

services:
  your.own.namespace.hello_world:
    class: Your\Own\Namespace\HelloWorldService

You'll then delegate the core-specific business logic to the new core classes allowing your custom step to be transparently run on both Drupal 7 and Drupal 8. Such a step would look like:

<?php
class TestContext extends RawDrupalContext { /**
   * @Given I publish the node of type :type and title :title
   */
 
public function iPublishTheNodeOfTypeAndTitle($type, $title) {
   
$this->getCore()->publishNode($type, $title);
  }

...

?>

Ready to use contexts

The extension also provides some utility contexts that you can use right away in your tests. Below a quick overview of what's currently available:

Context Description

NuvoleWeb\Drupal\DrupalExtension\Context\DrupalContext

Standard Drupal context. You want to use this one next to (and not instead of) Drupal\DrupalExtension\Context\DrupalContext.

NuvoleWeb\Drupal\DrupalExtension\Context\ContentContext

Perform operations on Content.

NuvoleWeb\Drupal\DrupalExtension\Context\CKEditorContext

Allows to interact with CKEditor components on your page.

NuvoleWeb\Drupal\DrupalExtension\Context\ResponsiveContext:
  devices:
    mobile_portrait: 360x640
    mobile_landscape: 640x360
    tablet_portrait: 768x1024
    tablet_landscape: 1024x768
    laptop: 1280x800
    desktop: 2560x1440

Resize the browser according to the specified devices, useful for testing responsive behaviors.

NuvoleWeb\Drupal\DrupalExtension\Context\PositionContext

Check position of elements on the page.

NuvoleWeb\Drupal\DrupalExtension\Context\ChosenFieldContext

Interact with Chosen elements on the page.

We will share more steps in the future enriching the current contexts as well as providing new ones so keep an eye on the project repository!

Disclaimer

At the moment only Drupal 8 is supported but we will add Drupal 7 support ASAP (yes, it's as easy as providing missing Drupal 7 driver core methods and adding tests).

Aug 23 2016
Aug 23

Answering the most commonly asked question about Configuration Management in Drupal 8; and a preview of our DrupalCon training.

This post is an excerpt from the topics covered by our DrupalCon Dublin training: Drupal 8 Development - Workflows and Tools.

For the last two years we have been giving trainings and presentations at various Drupal events about configuration management and its new workflows in Drupal 8. One of the recurring questions has been:

How do I keep some configuration from being deployed? For example the devel module and its configuration?

Until now we have answered to use drush with the --skip-modules flag and then to gitignore the configuration for devel. But then you can't share the development configuration and the process is error prone when there are more modules and other configuration items that depend on the configuration you gitignore.

For some simpler cases where configuration needs to be different between environments (for example the error verbosity) the configuration override system allows to override the configuration in settings.php. This is a solution for some cases, however, you can not override which modules are enabled or override configuration that doesn't exist.

Enter: Configuration split!

Our new module Configuration split splits the configuration when exporting it with a special Drupal Console command. It can be configured to split out enabled modules and given blacklisted configuration and it will then separate all the configuration that is dependent on the listed modules or configuration. The module's settings also allow to set a folder to which the separated configuration will be exported to.

That way the configuration set which you use to deploy configuration between different environments is a subset of your development configuration and the trusty configuration system of Drupal 8 can be used unharmed. Of course when importing with the special command the split configuration is merged back, allowing you to keep your development configuration in place.

"To split" is a synonym for "to break" and as such "Configuration split" has a dangerous ring to it. This is on purpose because the exported subset is on purpose not what you have on your development site and not what you have locally tested. So you need to compensate that with a workflow that imports and verifies the configuration you are going to deploy. This is better than to import and export individual configuration because Drupal needs the whole set of configuration to do its checks.

How do I use it?

Download and enable the Configuration split module like any other module. Then configure it under admin/config/development/configuration/config_split. Set the split folder to a different folder than your normal config sync folder. If you want a prettier interface, consider using Chosen. Then use the Drupal Console command config_split:export and config_split:import to export and import respectively.

Let's look at the devel example from above. We typically version the configuration outside of the webroot in ../config/sync as seen by Drupal. (In the project root when starting a project with drupal-composer/drupal-project.) So the folder we specify for config_split would be ../config/dev. The module to filter would be Devel and the rest can be left empty. The devel.settings will be detected automatically. Note though that the system.menu.devel does not depend on the devel module and can not be detected automatically, but it is easy to add it to the blacklisted config and it could theoretically be deployed without breaking anything.

Configuration Split settings form with chosen

The resulting config_split.settings.yml could look something like this when exporting it:

folder: ../config/dev
module:
  devel: 0
theme: {  }
blacklist:
  - system.menu.devel

Finally the following command will export the configuration to the default sync directory without the devel module enabled and export the devel configuration into the dev directory.
web$ ../vendor/bin/drupal config_split:export

Now if you would import the configuration through the UI or with drush cim the devel module would be un-installed, and you can do that to see the site without its development configuration. However, If you want the development configuration to stay or become active and the devel module installed use the following command:
web$ ../vendor/bin/drupal config_split:import

How does it work internally?

We implemented a StorageWrapper that allows filters to interact with the configuration after it has been read and before it is written to the wrapped FileStorage during the import and export operation. The SplitFilter has a secondary storage and decides where to read from or write to. This is a very similar concept to what drush does with its --skip-modules flag since we will want to easily integrate this with drush in the future.

What comes next?

The module is still in an early development stage and some more additions in the scope of splitting configuration could be added. The subset without the split configuration could be verified after exporting it and we could warn the user if it couldn't be imported. Or for example we currently use only config_split.settings but if the need arises we could support multiple split configurations. Or we could add a "gray list" to ignore some configuration that exists rather than removing it when splitting, essentially making it a configuration override outside of the scope of Drupal's runtime. This could be useful when maintaining several sites that are almost the same but all have their little "special snowflake" configuration which in turn could be synchronized with the normal workflow.

It is important to understand that the configuration system of Drupal has limitations that are there for a good reason. Most of them are to ensure data integrity and robustness and reliability of the synchronisation and so on. In other words measures to protect you from accidentally breaking your site. Using tools like config_split or drush --skip-modules you circumvent some of these security and integrity checks so use them with caution.

Since the module is not required for the regular functioning of a Drupal 8 site (it can even be used to blacklist itself) it can already be used in the development process of your current projects already. Your feedback is welcome, see you in the issue queue.

Aug 19 2016
Aug 19

Considerations following our Drupal Dev Day Milan and Drupalaton presentations; and a preview of our DrupalCon training.

This post is an excerpt from the topics covered by our DrupalCon Dublin training: Drupal 8 Development - Workflows and Tools.

During the recent Nuvole presentations at Drupal Dev Days Milan 2016 and Drupalaton Hungary 2016 we received a number of questions on how to properly setup a Drupal 8 project with Composer. An interesting case where we discovered that existing practices are completely different from each other is: "What is the best way to deploy a Composer-based Drupal 8 project?".

We'll quickly discuss some options and describe what works best for us.

What to commit

You should commit:

  • The composer.json file: this is obvious when using Composer.
  • The composer.lock file: this is important since it will allow you to rebuild the entire codebase at the same status it was at a given point in the past.

The fully built site is commonly left out of the repository. But this also means that you need to find a way for rebuilding and deploying the codebase safely.

Don't run Composer on the production server

You would clearly never run composer update on the production server, as you want to be sure that you will be deploying the same code you have been developing upon. For a while, we considered it to be enough to have Composer installed on the server and run composer install to get predictable results from the (committed) composer.lock file.

Then we discovered that this approach has a few shortcomings:

  • The process is not robust. A transient network error or timeout might result in a failed build, thus introducing uncertainty factors in the deploy scripts. Easy to handle, but still not desirable as part of a delicate step such as deployment.

  • The process will inevitably take long. If you run composer install in the webroot directly, your codebase will be unstable for a few minutes. This is orders of magnitude longer than a standard update process (i.e., running drush updb and drush cim) and it may affect your site availability. This can be circumvented by building in a separate directory and then symlinking or moving directories.

  • Even composer install can be unpredictable, especially on servers with restrictions or running different versions of Composer or PHP; in rare circumstances, a build may succeed but yield a different codebase. This can be mitigated by enforcing (e.g., through Docker or virtualization) a dev/staging environment that matches the production environment, but you are still losing control on a relatively lengthy process.

  • You have no way of properly testing the newly built codebase after building it and before making it live.

  • Composer simply does not belong in a production server. It is a tool with a different scope, unrelated to the main tasks of a production server.

Where to build the codebase? CI to the rescue

After ruling out the production server, where should the codebase be built then?

Building it locally (i.e., using a developer's environment) can't work: besides the differences between the development and the production (--no-dev) setup, there is the risk of missing possible small patches applied to the local codebase. And a totally clean build is always necessary anyway.

We ended up using Continuous Integration for this task. Besides the standard CI job, which operates after any push operation to the branches under active development, performs a clean installation and runs automated tests, another CI job builds the full codebase based on the master branch and the composer.lock file. This allows sharing it between developers, a fast deployment to production through a tarball or rsync, and opportunities for actually testing the upgrade (with a process like: automatically import the production database, run database updates, import the new configuration, run a subset of automated tests to ensure that basic site functionality has no regressions) for maximum safety.

Slides from our recent presentations, mostly focused on Configuration Management but covering part of this discussion too, are below.

Aug 10 2015
Aug 10

Drupal 8 Configuration Management: beware of pitfalls

Fabian Bircher

10 Aug 2015

0 Comments

Fabian Bircher

10 Aug 2015

0 Comments

Fabian Bircher, 10 Aug 2015 - 0 Comments

Nuvole's Configuration Management workshop at Drupalaton 2015 in Hungary

Drupalaton in Hungary last weekend gave the opportunity for a 90 minutes workshop about Configuration Management (CMI) and how it changes a Drupal developers work flow with the coming Drupal 8.

CMI allows you to have the whole site configuration under control and that is a great improvement. But it also comes with its pitfalls. Developers have to be more vigilant when sharing configuration with each other: mindless exporting configuration may override the configuration shared by others, mindless importing may override one's own work and forgetting to import merged configuration leads to ignoring the work of your co-developers at a later stage.

CMI, while it is much more awesome than anything we have in Drupal 7, is also much more unforgiving. So it would be all too easy to not use it properly and what it was designed for and then wonder why you can't have nice things.

Fortunately, a methodical git workflow can help recover from mistakes (except importing configuration before exporting it first). So don't forget the order of the steps:

  1. config export
  2. git commit
  3. git merge
  4. config import

And do it often to keep the merges and failures simple and easy to resolve.

Please find the full Drupalaton 2015 workshop slides attached below.

CMI-drupalaton2015.pdf (745.87 KB)Download
Apr 27 2015
Apr 27

Use Features together with a configuration management workflow and get the best of both worlds.

This is a preview of Nuvole's training at DrupalCon Los Angeles: "An Effective Development Workflow in Drupal 8".

Features for Drupal 8 will exist and it is already in alpha state. This may be surprising to those who wrongly assumed that Configuration Management was going to supersede Features; but, as we explained before, it all comes down to understanding how to use Features the right way in Drupal 8.

If you are using Features in Drupal 8 for deployment of configuration, you are doing it wrong!™

The role of Features

While the configuration management was built to keep configuration consistent and enable deploying it between different environments of the same site it was not built for sharing configuration between different sites. This is where Features comes in. Features allows you to easily bundle related configuration and re-use it on another site.

For re-using configuration and building starter profiles the current alpha version is already great. It works just like the re-usable “feature” we were blogging about last year, except it comes with a familiar UI and lets you do everything as a site builder. It even comes with a smart system that auto detects configuration that belongs together. Features-overview

Features-export

Configuration changes are development

Developers and site builders working with configuration in Drupal 8 need to understand that changing configuration needs to be treated equally with development. While this may seem trivial at first, the consequences are a fundamental shift to the approach of building a Drupal 8 site.

Drupal 8 comes with the configuration management system that was built to deploy configuration between different environments of the same site. It allows the whole configuration of a site to be synchronized both through the UI for “site builders” and through drush and git for “developers”. While the system allows individual configuration objects to be exported and imported, deployment and synchronization is always done with the entire set to ensure it is consistent.

This means that when you change configuration on a production site you either opt out of using the configuration management to deploy configuration or you need to go through a more elaborate work flow to synchronize the configuration changes with the development environments similar to what you would need to do if you were to change code directly on the production server.

For the math-oriented,

Δ config ⊆ development

What if you want to be free of the temptation to edit configuration in production? Luckily there is a module for that! It is called Configuration read-only mode and allows to lock the forms where you change the configuration, thus enforcing its role as a "developers only" tool.

Of course some configuration will differ between environments. Just as the database credentials are kept separate from the rest of the code, specific configuration can be overridden in the instances’ settings.php or services.yml. The rest of the code is usually treated as a whole for consistency reasons, the same should be true for configuration.

What about not using configuration management?

Features and packaging related modules should not be regarded as a solution to deploy only partial configuration. Packaged configuration by definition is never aware of the whole site and the possible inter-dependencies of the site's particular configuration. Deploying only partial configuration circumvents the safeguards Drupal put in place to make the deployment more robust. Of course nobody is forced to use the new tools for configuration management and you can easily opt out of using it by just ignoring that option. It is also still possible to develop a Drupal 8 site by sharing a database dump just as with Drupal 5. But remember that a Drupal 7 approach will yield the Drupal 7 headaches. We would recommend re-evaluating the deployment strategies when starting to use Drupal 8.

Managing distributions in Drupal 8

The more complicated scenario which is yet to be tackled is a feature for a richer distribution which will update over time. For example a newer version of a feature could come with an updated view or additional or updated fields for a content type.

First steps in that direction have already been taken by Configuration Update Manager (a dependency of features) and Configuration Synchronizer (a sandbox module). Configuration Update Manager compares the configuration in use on the site with the configuration which was provided by a module or installation profile. Configuration Synchronizer goes a step further and keeps a snapshot of the configuration when it was installed in order to determine whether the configuration has been customized by an administrator or whether it can safely be updated to the one provided in the new version of the module/feature.

All the modules mentioned above are used in a development environment of a particular site. Or in other words in an environment where configuration changes are expected and part of the process of updating a site.

For more, see our presentation from the Drupal Developer Days (embedded below); thanks to all the people there for the fruitful discussions we had on this topic during the event.

Mar 24 2015
Mar 24

Write more complete Behat test scenarios for both Drupal 7 and Drupal 8.

On of the main goal of BDD (Behaviour Driven Development) is to be able to describe a system's behavior using a single notation, in order to be directly accessible by product owners and developers and testable using automatic conversion tools.

In the PHP world, Behat is the tool of choice. Behat allows to write test scenarios using Gherkin step definitions and it generates the corresponding PHP code to actually run and test the defined scenarios.

Thanks to the excellent Behat Drupal Extension Drupal developers have been able to enjoy the benefits of Behavioral Driven Development for quite some time.

Essentially the project provides an integration between Drupal and Behat allowing the usage of Drupal-specific Gherkin step definitions. For example, writing a scenario that tests node authorship would look like:

Scenario: Create nodes with specific authorship
  Given users:
  | name     | mail            | status |
  | Joe User | [email protected] | 1      |
  And "article" content:
  | title          | author   | body             |
  | Article by Joe | Joe User | PLACEHOLDER BODY |
  When I am logged in as a user with the "administrator" role
  And I am on the homepage
  And I follow "Article by Joe"
  Then I should see the link "Joe User"

Dealing with complex content types

The Gherkin scenario above is pretty straightforward and it gets the job done for simple cases. In a real-life situation, though, it's very common to have content types with a high number of fields, often of different types and, possibly, referencing other entities.

The following scenario might be a much more common situation for a Drupal developer:

Scenario: Reference site pages from within a "Post" node
  Given "page" content:
    | title      |
    | Page one   |
    | Page two   |
    | Page three |
  When I am viewing a "post" content:
    | title                | Post title         |
    | body                 | PLACEHOLDER BODY   |
    | field_post_reference | Page one, Page two |
  Then I should see "Page one"
  And I should see "Page two"

While it is always possible to implement project specific step-definition, as show on this Gist dealing with field collections and entity references, having to do that for every specific content type might be an unnecessary burden.

Introducing field-handling for the Behat Drupal Extension

Nuvole recently contributed a field-handling system that would allow the scenario above to be ran out of the box, without having to implement any custom step definition, working both in Drupal 7 and Drupal 8. The idea behind it is to allow a Drupal developer to work with fields when writing Behat test scenarios, regardless of the entity type or of any field-specific implementation.

The code is currently available on the master branches of both the Behat Drupal Extension and the Drupal Driver projects, if you want to try it out follow the instructions at "Stand-alone installation" and make sure to grab the right code by specifying the right package versions in your composer.json file:

{
  "require": {
    "drupal/drupal-extension": "3.0.*@dev",
    "drupal/drupal-driver": "1.1.*@dev"
}

The field-handling system provides an integration with several highly-used field types, like:

Date fields

Date field values can be included in a test scenario by using the following notation:

  • Single date field value can be expressed as 2015-02-08 17:45:00
  • Start and end date are separated by a dash -, for ex. 2015-02-08 17:45:00 - 2015-02-08 19:45:00.
  • Multiple date field values are separated by a comma ,

For example, the following Gherkin notation will create a node with 3 date fields:

When I am viewing a "post" content:
  | title       | Post title                                |
  | field_date1 | 2015-02-08 17:45:00                       |
  | field_date2 | 2015-02-08 17:45:00, 2015-02-09 17:45:00  |
  | field_date3 | 2015-02-08 17:45:00 - 2015-02-08 19:45:00 |

Entity reference fields

Entity reference field values can be expressed by simply specifying the referenced entity's label field (e.g. the node's title or the term's name). Such an approach wants to keep up with BDD's promise: i.e. describing the system behavior by abstracting, as much as possible, any internal implementation.

For example, to reference to a content item with title "Page one" we can simply write:

When I am viewing a "post" content:
  | title           | Post title |
  | field_reference | Page one   |

Or, in case of multiple fields, titles will be separated by a comma:

When I am viewing a "post" content:
  | title           | Post title         |
  | field_reference | Page one, Page two |

Link fields

A Link field in Drupal offers quite a wide range of options, such as an optional link title or internal/external URLs. We can use the following notation to work with links in our test scenarios:

When I am viewing a "post" content:
  | title       | Post title                                              |
  | field_link1 | http://nuvole.org                                       |
  | field_link2 | Link 1 - http://nuvole.org                              |
  | field_link3 | Link 1 - http://nuvole.org, Link 2 - http://example.com |

As you can see we use always the same pattern: a dash - to separate parts of the same field value and a comma , to separate multiple field values.

Text fields with "Select" widget

We can also refer to a select list value by simply referring to its label, so to have much more readable test scenarios. For example, given the following allowed values for a select field:

option1|Single room
option2|Twin room
option3|Double room

In our test scenario, we can simply write:

When I am viewing a "post" content:
  | title      | Post title               |
  | field_room | Single room, Double room |

Working with other entity types

Field-handling works with other entity types too, such as users and taxonomy terms. We can easily have a scenario that would create a bunch of users with their relative fields by writing:

Given users:
  | name    | mail                | language | field_name | field_surname | field_country  |
  | antonio | [email protected] | it       | Antonio    | De Marco      | Belgium        |
  | andrea  | [email protected]  | it       | Andrea     | Pescetti      | Italy          |
  | fabian  | [email protected]  | de       | Fabian     | Bircher       | Czech Republic |

Contributing to the project

At the moment field-handling is still a work in progress and, while it does support both Drupal 7 and Drupal 8, it covers only a limited set of field types, such as:

  • Simple text fields
  • Date fields
  • Entity reference fields
  • Link fields
  • List text fields
  • Taxonomy term reference fields

If you want to contribute to the project by providing additional field type handlers you will need to implement this very simple, core-agnostic, interface:

<?php
namespace Drupal\Driver\Fields;/**
* Interface FieldHandlerInterface
* @package Drupal\Driver\Fields
*/
interface FieldHandlerInterface { /**
   * Expand raw field values in a format compatible with entity_save().
   *
   * @param $values
   *    Raw field values array.
   * @return array
   *    Expanded field values array.
   */
 
public function expand($values);
}
?>

If you need some inspiration check the current handlers implementation by inspecting classes namespaced as \Drupal\Driver\Fields\Drupal7 and \Drupal\Driver\Fields\Drupal8.

Dec 08 2014
Dec 08

Nuvole's files and documents management feature is now available for the latest version of Open Atrium

We received many requests to make an updated version of our Atrium Folders feature available for the latest version of Open Atrium, the excellent Drupal-based solution for Intranets developed by Phase2.

OECD sponsored the development of the new version as an open source project, in order to add a file management functionality to the Innovation Policy Platform site that it manages together with the World Bank. Atrium Folders for Open Atrium 2 is thus now available to everybody.

The usual features, a new way

Open Atrium changed completely and so did Atrium Folders. There are many differences under the hood, with a complete code rewrite, but the familiar user experience is still there.

Uploading and downloading files

Creating folders and adding files to the folders is as easy as creating any other content in Open Atrium 2: it is enough to create "Files sections". When you are viewing a folder, specific buttons allow to create subfolders, upload files and directly download any file.

Access management

The access management works like for other nodes in Open Atrium. Access to the folder can be restricted for both viewing and editing separately, and it can be determined at a folder level.

Notifications

The notification system of Open Atrium can also be used for folders. Users can be informed when new files are added, with the same interface used by other Open Atrium features.

And much more

Media module support

The files are attached with the Media widget and it is thus possible to manage not only files, but everything Media supports, like for example YouTube videos or files attached to other content.

Multiple uploads, with drag and drop support

The multi-upload feature of Open Atrium 2 can also be used with Folders to upload several files at the same time. Drag and drop uploads are supported too.

Download folder as ZIP file

The download button for files exists also for folders and it allows to download a folder with its subfolders and all included files as a ZIP archive. This functionality is available as a submodule, bundled with Atrium Folders.

File and folder revisions

Atrium Folders supports history and revisions both for folders and files. You can view previous versions of a file and optionally restore an older version. This functionality is available as a submodule, bundled with Atrium Folders.

Download, installation and support

The Open Atrium Folders feature can be downloaded and installed like any other module.

It is available on drupal.org at https://www.drupal.org/project/oa_folders/

Please report any issues in the module's issue queue at drupal.org

Oct 01 2014
Oct 01

Drupal 7 to Drupal 8: The Cheat Sheet

Andrea Pescetti

1 Oct 2014

0 Comments

Andrea Pescetti

1 Oct 2014

0 Comments

Andrea Pescetti, 1 Oct 2014 - 0 Comments

From our DrupalCon Amsterdam 2014 training

Our new An Effective Development Workflow in Drupal 8 training just made its debut at DrupalCon Amsterdam. An important part of the training is dedicated to shorten the trial-and-error period developers necessarily need to go through when converting their practices from Drupal 7 to Drupal 8: we want that proficient Drupal 7 (and Features) developers with zero, or very limited, Drupal 8 knowledge, gain a rather comprehensive knowledge of Drupal 8 (focused on configuration management) that allows them to be immediately productive when Drupal 8 is released.

As a gift to those who couldn't attend the training because it was sold out, and to all lovers of Drush, Features and code-driven development in general, we are sharing a "Drupal 7 to Drupal 8" cheatsheet that was part of the training materials. Please find it attached to this post, in PDF format.

We still have some printed copies available to give away; find us at DrupalCon and feel free to ask us for one!

Drupal-7-to-Drupal-8-Cheatsheet.pdf (999.82 KB)Download
Aug 20 2014
Aug 20

The D8 way to replace "features-update" and "features-revert-all".

This is a preview of Nuvole's training at DrupalCon Amsterdam: An Effective Development Workflow in Drupal 8.

One of the new key features of Drupal 8 is the possibility to deal with configuration in code. Since configuration is now in text files, we want to put it under version control in Git to enjoy the many advantages this brings: comparing configuration states, keeping a history of configuration changes and even moving configuration between sites.

Setup

We will assume that you have a development version of Drupal 8, git and drush available on your system. You can set up your Drupal git repository in several ways. One of them is outlined in Building a Drupal site with Git on drupal.org. The document is written for Drupal 7, but can easily be adapted for Drupal 8.
Another, probably simpler method is to simply download a Drupal 8 (alpha) release and initialise a new repository with it.

In either case you should copy example.gitignore to .gitignore and adapt it to your needs to prevent settings.php and the files directory from being versioned.

The next step is to make sure that a configuration directory is versionable. By default Drupal 8 will place the staging directory under sites/default/files and it is considered a good practice to not version that location, but an alternative location can easily be specified in settings.php:

<?php
$config_directories
['staging'] = 'config/staging';
?>

It is also possible and even advisable to specify a directory outside of the web root of course. In that case you would put the parent directory of your web root where drupal is under version control and use ../config/staging. We will later see that it is also possible to add more directories and keys to the $config_directories variable.

Because the configuration management of Drupal 8 only works between different instances of the same site, the different instances of the site need to be cloned. Cloning a Drupal 8 site is done the same way as cloning a Drupal 7 site. Just dump the database of the site to clone and import it in the other environment.

Development

After cloning your site you can go ahead and start configuring your site.
Once the part of the configuration you were working on is done the whole configuration of the site needs to be exported.

local$ drush config-export staging
The current contents of your export directory (config/staging) will be deleted. (y/n): y
Configuration successfully exported to config/staging.

Next, you need to merge the work of other developers. In some cases it may be enough to simply use git pull, otherwise the configuration has to be merged after it has been committed:

Git can merge changes in text files quite well, but git does not know about Drupal and its yaml format for configuration. It is, therefore, important to verify that the merged configuration makes sense and is valid. In most cases it will probably not be an issue and just work, but it is always better to be vigilant and be on the safe side. So, after merging, you should always run:

local$ drush config-import staging

If the import went smooth you can push the configuration to the remote repository. Otherwise the configuration needs to be fixed first.

Deployment

The simplest case is when the configuration on the production site has not been changed. There is an interesting Configuration Read-only mode module that can enforce this.

If the configuration did not change deploying the new configuration is simply:

remote$ git pull
remote$ drush config-import staging

If the configuration changes on the production site, it is best to frequently export the live configuration into a dedicated directory.
Add a new config directory in settings.php:

<?php
$config_directories
['to_dev'] = 'config/to_dev';
?>

remote$ drush config-export to_dev -y

Add, commit and push it to the production branch so that the developers can deal with it and integrate the changes into the configuration which will be deployed next. Exporting the configuration into a dedicated directory rather than the staging directory avoids the danger that merge conflicts happen on the production site. The deployment to the production site should be kept hassle free, so it should always be safe to pull from git and import the configuration without the risk of a conflict.

Important notes

It is important to first export the configuration changes and then pull changes from collaborators because the exporting action wipes the directory and re-populates it with the active configuration. Since everything is in git, you can recover from such a mistake without much difficulty but why make your life complicated.

Import the configuration before pushing it to the remote repository. Broken configuration breaks the site, be a nice co-worker.

Git doesn't solve everything! Imagine Alice and Bob start with the same site, it has one content type and among others an "attachment" field. Alice deletes the attachment field, exports the configuration and pushes it to git. In the meantime, Bob creates a new content type and adds the attachment field to it. Bob exports his configuration, merges Alice's configuration changes without a problem (the changes are separate files) and imports the merged configuration. The attentive reader sees where this leads. The commit of Alice deletes the field storage for the attachment field, but Bob added a field instance which depends on the field storage. The exported configuration now contains a field instance that can't be imported.
At the time of writing, drush will signal a successful import but doesn't actually import it while the UI is more helpful and complains that the attachment field instance was not imported due to the missing field storage.

Jul 15 2014
Jul 15

Bringing "reusable features" to Drupal 8.

This is a preview of Nuvole's training at DrupalCon Amsterdam: An Effective Development Workflow in Drupal 8.

Configuration Management in Drupal 8 elegantly solves staging configuration between different environments addressing an issue that is still haunting even the most experienced Drupal 7 developer. In earlier posts we covered the new Configuration Management in Drupal 8, seeing how it compares to Drupal 7 and Features, and even investigated how to manually simulate Features in Drupal 8 last year. Recent developments and contrib modules can take us several steps closer.

Packaging configuration

Developers familiar with code-driven development practices need an equivalent in Drupal 8 + Drush 7 to what the Features module does in Drupal 7 with its features-update and features-revert Drush commands.

While Drupal 8 configuration staging capabilities are far more advanced than what Features could possibly provide, what the new Configuration Management system really lacks is the ability to package configuration.

Enter the Configuration development module

The Configuration development module, currently maintained by chx, serves two main purposes:

  • It automates the import of specified configuration files into the active storage.
  • It automates the export of specified configuration objects into files.

The module offers a simple, global UI interface where a Drupal developer can set which configuration is automatically exported and imported any time they hit the “Save” button on a configuration setting page.

In order to achieve a more modular configuration packaging it would be enough to set a specific module’s config/install directory as the actual export destination.

Nuvole contributed a patch (EDIT: now integrated) to make that possible: instead of firing an auto-export every time a “Save” button is clicked the developer can, instead, specify in the module’s info file which configuration needs to be written back to that module’s install directory and run a simple Drush command to do that.

Reusable “features” in Drupal 8

One of the main advantages of having a standardized way of dealing with configuration means that modules can now stage configuration at installation time. In a way that’s something very close to what Features allowed us to do in Drupal 7.

Say we have our news section up and running on the site we are currently working on and we would like to package it into a custom module, together with some other custom code, and ship it over a new project. The patched Config development module will help us to do just that! Here it is how:

Step 1: Download, patch and enable Configuration development module

We need to download and enable the Configuration development module and apply the patch (EDIT: already integrated as of 8.x-1.0-alpha7) attached to this Drupal.org issue.

After rebuilding the cache, we will have the config-writeback Drush command available. Let's have a closer look at what it is meant to do:

$ drush help config-writeback

Write back configuration to a module's config/install directory. State which configuration settings you want to export in the module's info file by listing them under 'config_devel', as shown below:

config_devel:
  - entity.view_display.node.article.default
  - entity.view_display.node.article.teaser
  - field.instance.node.article.body

Examples:
drush config-writeback MODULE_NAME        Write back configuration to the specified module, based on .info file.

Arguments:
module                                    Module machine name.

Aliases: cwb

Step 2: Find what configuration needs to be packaged

We now look for all configuration related to our site’s news section. In Drupal 8 most of the site configuration is namespaced with related components so, if we keep on using consistent naming conventions, we can easily list all news-related configuration by simply running:

$ drush config-list | grep news

entity.form_display.node.news.default
entity.view_display.node.news.default
entity.view_display.node.news.teaser
field.instance.node.news.body
image.style.news_medium
menu.entity.node.news
node.type.news

Step 3: Package configuration

To package all the settings above we will create a module called custom_news and, in its info file, we will specify all the settings we want to export, listing them under the config_devel: directive, as follows:

$ cat modules/custom_news/custom_news.info.yml

name: Custom News
type: module
description: 'Custom news module.'
package: Custom
core: 8.x
config_devel:
  - entity.form_display.node.news.default
  - entity.view_display.node.news.default
  - entity.view_display.node.news.teaser
  - field.instance.node.news.body
  - image.style.news_medium
  - menu.entity.node.news
  - node.type.news

After enabling the module we will run:

$ drush config-writeback custom_news

And we will have all our settings exported into the module’s install directory:

$ tree -L 3 modules/custom_news/

modules/custom_news/
├── config
│   └── install
│       ├── entity.view_display.node.news.default.yml
│       ├── entity.view_display.node.news.teaser.yml
│       ├── field.instance.node.news.body.yml
│       ├── image.style.news_medium.yml
│       ├── menu.entity.node.news.yml
│       └── node.type.news.yml
└── custom_news.info.yml

The Drush command above takes care of clearing all sensitive UUID values making sure that the module will stage the exported configuration cleanly, once enabled on a new Drupal 8 site.

To get the news section on another site we will just copy the module to the new site's ./modules/ directory and enable it:

$ drush en custom_news

The following extensions will be enabled: custom_news
Do you really want to continue? (y/n): y
custom_news was enabled successfully.     

Final evaluation: Drupal 7 versus Drupal 8

One of the main differences between working in Drupal 7 and in Drupal 8 is represented by the new Configuration Management system.

While Features was proposing a one-stop solution for both configuration staging and packaging, Drupal 8 CM does a better job in keeping them separate, allowing developers in taking a greater control over these two different and, at the same time, complementary aspect of a solid Drupal development workflow.

By using the method described above we can upgrade our comparison table between Drupal 7 and Drupal 8 introduced in one of our previous posts as follows:

Functionality D7 Core D7 Core + Features D8 Core (current) D8 Core (current) + Config Devel Export full site config (no content) NO NO YES YES Export selected config items NO YES YES YES Track config changes (full site) NO NO YES YES Track config changes (selected items) NO YES YES YES Stage configuration NO YES YES YES Package configuration NO YES NO YES Reuse configuration in other projects NO YES NO YES Collaborate on the same project NO YES NO NO

The last "NO" deserves a brief explanation: Configuration Management allows two developers to work simultaneously on different parts of the same project if they are very careful: but "merging" the work would have to be done by version control (GIT or similar), that doesn't know about YAML or Drupal.

Some open issues

Contributed modules seem to be the best way to enhance the core Configuration Management system, much like what happened with Drupal 7 and Features. There are still several issues that should be considered for an optimal workflow, to match and improve what we already have in Drupal 7:

  • Piping: the ability to relate configuration components based on both hard and logic dependencies, for example: I export a content type and, automatically, I get also its fields. If piping might have been too rigid, at times, it would be still useful to have in some configurable form.
  • Enhanced configuration diff: it might be useful to have the possibility to review what configuration is going to be installed before enabling a module, like it is now when importing staged configuration to the active storage.
  • Granularity: it is still impossible to export part of a configuration file, so we still depend on the core conventions for grouping configuration into files, and we can't export a single permission for example.
  • Ownership: we can't know if another module (or "feature") is tracking a component we wish to track; this could be useful in the perspective of maintaining several "modular" features.
  • Updates: we can reuse configuration by simply enabling a module, but this holds only for the initial installation; after a module is enabled, we don't have a clean way to import changes (say, to "upgrade" to a newer version of the feature) outside the standard workflow foreseen in Configuration Management.
Jun 06 2014
Jun 06

Features done right? Features done wrong? What changed, what improved, what's still missing.

This is a preview of Nuvole's training at DrupalCon Amsterdam: "An Effective Development Workflow in Drupal 8".

Nuvole gave two talks about the current status of Configuration Management in Drupal 8 at European Drupal events in the last few weeks: Drupal Days Milan 2014 and Drupal Camp Alpe Adria 2014.

Developers attending the events were mostly interested in how the future Drupal 8 Configuration Management capabilities will compare to Drupal 7, with and without the Features module (or, in general, with and without what we call the code-driven workflow).

Here is a comparison based on the current status of Drupal 8. Please note that CMI, the Configuration Management Initiative, is still under active development, and for example a couple issues mentioned in the slides have already been resolved, shortly after we gave our presentations. The very basic concepts, though, remain unchanged from our September 2013 post, so you might want to review that one if you have never heard about CMI before.

Configuration Management: Key differences between Drupal 7 and Drupal 8

Configuration is well-defined

In Drupal 7 it isn't always clear-cut whether something belongs in the "configuration" or "content" realm. Are vocabularies configuration? Are taxonomy terms configuration? And what about a taxonomy term whose ID is used as a contextual filter in a View? Several approaches to this are possible, like soft configuration.

In Drupal 8, configuration will be less subjective: Drupal has an "Export Configuration" function that exports all the site configuration; if something is not there, it is not considered to be configuration. Concepts like soft configuration still apply, but at least it's clear what is configuration and is not.

Configuration is stored in files

Drupal 7, generally, stores configuration in the database, together with content. Only a little subset of configuration is read from PHP files. In Drupal 8 configuration will live in text files. Then, for several reasons (performance, safety, security), those files will actually be stored in the database by default (one of the most visible recent changes), but will still be accessed and managed as files.

Unified format and approach to configuration

A particularly annoying issue with Drupal 7 is that modules are free to set their own standards for storing configuration, so it is common to find sites where configuration is scattered among variables, database tables, objects exported via CTools, Features, and other places. Modules like Features at times need some "black magic" to guess where and how relevant configuration is stored.

The unified approach in Drupal 8, where all configuration is in the form of text files in the YAML format, is a great step forward. It removes the guesswork needed by Features in Drupal 7 to understand how to find and export components.

Staging configuration

In Drupal 7 you can have "staged configuration" through Features and the Features revert operation. Drupal 8 will introduce, out of the box, an "Import Configuration" facility that you can use to import either the whole site configuration or a single configuration file. The approaches are mostly equivalent, but on one side Drupal 7 + Features offers better packaging functionality, on the other side Drupal 8 will allow to import a complete site configuration (all variables, permissions...), something that is highly unpractical to do with Drupal 7 and Features.

Interface to developers

From a developer's point of view, writing PHP code to access and/or set a component's configuration in Drupal 7 is tricky, since you don't have a global interface, let alone an "entry point" that allows you to explore all the site configuration: you are forced to use a mixed bag of tricks ranging from variable_get() and variable_set() to database queries, to Ctools hooks for making configuration exportable and so on.

Drupal 8 will bring a very welcome improvement by providing a dedicated type for configuration entities and the unified interface Drupal::config($name) for getting and setting all configuration values: as a typical example Drupal::config('system.site')->get('name') will return the site name, and the same pattern can be used for everything.

The shootout: Drupal 7 vs Drupal 7 + Features vs Drupal 8

A quick feature comparison table between Drupal 7 core, Drupal 7 + Features and the current state of Drupal 8. As you see, a developer that is now using Drupal 7 without features will see spectacular advantages in Drupal 8, while experienced users of Drupal 7 and Features will still miss something.

Functionality D7 Core D7 Core + Features D8 Core (current) Export full site config (no content) NO NO YES Export selected config items NO YES YES Track config changes (full site) NO NO YES Track config changes (selected items) NO YES YES Stage configuration NO YES YES Package configuration NO YES NO Reuse configuration in other projects NO YES NO Collaborate on the same project NO YES NO

What is still missing?

It's important to understand the use case for CMI. The stated aim for CMI is not to replace Features. CMI aims at making it much simpler to transport configuration changes from development to production, and this aim was reached.

All other benefits of Features are out of scope for CMI. These include: packaging configuration, reusing configuration in other projects (and not simply moving it between the development and production version of the same site) and enabling real-time team collaboration (developer A and developer B build two separate features for the same site, like the News and Blog sections, simultaneously). So there is definitely room for a Drupal 8 version of Features.

Is CMI “Features Done Right”?

No. It is a nice way to replace and improve one use case for Features: making configuration exportable into text files.

Is CMI “Features Done Wrong”?

No. It is a huge step forward to developers and it paves the way for additional modules that could offer the same functionality of Drupal 7 + Features in a much cleaner and more reliable way.

See full versions of our Milan and Alpe Adria presentations as a Slideshare embeds or PDF files, below.

Sep 03 2013
Sep 03

What CMI will bring to D8 and "Poorman's Features" for packaging configuration in D8

An update to this post is now available at http://nuvole.org/blog/2014/jul/15/packaging-and-reusing-configuration-d....

We have always told attendees of our Drupal 7 "Code-driven development" trainings that embracing the idea that configuration must be stored in files and not in the database would make their Drupal development future-ready: the specific processes would necessarily change but the concept would stay and be reinforced in Drupal 8, thanks to the nice work being done in the Configuration Management Initiative.

And this was right. The progress done in CMI is very good, to the point that in our coming DrupalCon training in Prague, Code-Driven Development: an Effective Drupal Workflow, from D7 to D8 we will explore in detail how things work in Drupal 7, but for each topic we'll also describe what is going to improve/change in Drupal 8.

Configuration Management in a nutshell

From a site builder's point of view, Configuration Management in Drupal 8 is visible as two items in admin/config/development: "Configuration Export" and "Configuration Import".

The Export functionality has no further options, and it provides you with a config.tar.gz file containing hundreds (180+ on a clean installation, many more on a feature-rich test site) of files in YAML format, human- and machine-readable. All the site configuration is there: node types, their fields, permissions, Views, theme settings, variables...

The Import functionality, on the converse, will import a config.tar.gz file, show you any configuration changes between the currently active configuration and the one you are trying to import and allow you to replace the current configuration with the one in the provided files.

config-import

For many developers, this is a dream come true: with D8, Drupal Core will support a file-based configuration, allowing developers to track changes, put configuration under version control, update a production site cleanly... basically, all the advantages that we have described as selling points for the Features module in the last several years.

The Future of Features

So, if the major selling points of the Features module are now in core, does Features have a future in Drupal 8?

It still does, but it needs to be repurposed. So far, it had a dual functionality, serving as:

  • A machinery to export/import configuration from database to code. This will no longer be necessary in Drupal 8. Configuration lives in files and the database is used only for caching. For the same reason, an important problem in Drupal 7 development ("How do I make configuration exportable when there is no native support for Features?") is now solved for good.

  • A convenient way to package and reuse configuration across multiple sites. This is extremely useful to developers and not completely covered by Configuration Management in Drupal 8, even though the basic components are there.

Poorman's Features: emulating Features in Drupal 8

Let's see how it is possible to package configuration and emulate, manually, what Features and Drupal 7 allow today.

As an example use case, we will package a "Blog Feature".

1: Create and export configuration

Create the Blog content type, configure its fields (use proper naming for fields: field_blog_image and so on) and a classic view with a block and page display. Then go to admin/config/development and export your configuration into the config.tar.gz file.

2: Package relevant configuration into a module

Create a simple feature_blog module containing:

  • feature_blog.info.yml: a basic .info file in the Drupal 8 format.

name: Blog
type: module
description: 'A Blog content type and related configuration.'
package: Features
version: 8.x-0.1
core: 8.x

  • feature_blog.module: an empty module file, needed for correct Drupal operations.

<?php
  // Drupal needs this empty file.

  • a config subdirectory: copy to this folder all relevant files from config.tar.gz; filenames are quite helpful here, as it will be enough to copy all files that have "blog" in their name.

.
|-- config
|   |-- entity.display.comment.comment_node_blog.default.yml
|   |-- entity.display.node.blog.default.yml
|   |-- entity.display.node.blog.teaser.yml
|   |-- entity.form_display.comment.comment_node_blog.default.yml
|   |-- entity.form_display.node.blog.default.yml
|   |-- field.field.field_blog_image.yml
|   |-- field.instance.comment.comment_node_blog.comment_body.yml
|   |-- field.instance.node.blog.body.yml
|   |-- field.instance.node.blog.field_blog_image.yml
|   |-- node.type.blog.yml
|   `-- views.view.blog.yml
|-- feature_blog.info.yml
`-- feature_blog.module

3: Make the exported files portable (remove UUIDs)

The feature is ready, but it will only work if imported in the same Drupal 8 site. We need to make it portable to other sites.

The main problem here is that Drupal assigns UUIDs (Universally Unique Identifiers) to each component. When you add, say, an "image" field to a content type, you create an instance of the "image" field, and to describe this relationship Drupal will rely on the UUID of the "image" field. Since UUIDs are site-specific, trying to import this configuration on another site would result in an error message like:

Drupal\field\FieldException: Attempt to create an instance of
unknown field 84e904df-2f14-46e8-9700-e00c5ca3f7d3
in Drupal\field\Entity\FieldInstance->__construct()
(line 252 of .../core/modules/field/lib/Drupal/field/Entity/FieldInstance.php).

Fortunately, in this case configuration import is designed to accept either names or UUIDs for describing the field this is an instance of. So it is enough to edit all files containing field.instance in their name and manually replace UUIDs with machine names (or just add machine names), something like the following:

-field_uuid: 84e904df-2f14-46e8-9700-e00c5ca3f7d3
+field_name: field_blog_image

Note that this relies on the specific handling of the FieldInstance class and may not be a general solution.

Edit: also note (see comments) that it is important to include a hardcoded UUID if you want to avoid that your configuration items are seen by Drupal as different items between your development and production sites, causing configuration import/export between the two to fail.

4: Import the feature on another site

Our module/feature is now ready to be imported. Just copy it to the /modules folder on another site, or a subfolder of it (this is now the recommended location to add modules) and enable it.

Your content type and configuration will be immediately available.

Possible improvements

The Configuration Management in Drupal 8 will bring to Drupal Core a clean, unified, professional way to deal with configuration. There will still be the need for a module like Features for packaging and reusing configuration.

Some implementation details of Configuration Management do not behave well in this respect: for example, UUIDs are problematic and user permissions are stored in a packaging-unfriendly way (one file per each user role, with roles identified by UUID).

But, overall, the future looks bright and code-driven! And, as we have seen, it is already entirely possible to manually create basic "Features" (i.e., modules with configuration) that will work in Drupal 8.

Oct 18 2012
Oct 18

Effective today, I (Andrea) have become an officer of the Apache Software Foundation, in my new role as Vice President for the Apache OpenOffice (commonly known as "OpenOffice") project.

This doesn't change much in my daily activity as director of Nuvole. I have been involved in the OpenOffice project for several years, starting much earlier than Drupal became a mainstream project. It has been and it will continue to be a volunteer activity, even though it will definitely happen that I attend more Apache events in the near future.

That said, this might be an occasion for the Drupal community to take a closer look at the Apache Software Foundation and its projects.

Even though there are still many people who identify Apache with its ubiquitous Apache HTTP server, the Apache Software Foundation is much larger than that: it is a huge, not-for-profit organization developing around 150 free and open source projects for the public good.

There are interesting opportunities for cooperation between Drupal and Apache projects: Apache Solr, for example, has already become a standard topic at Drupal events; Apache POI, Apache Tika and Apache PDFBox can extract text and metadata from Office or PDF documents and make them search-friendly, with initial work towards Drupal integration; Apache Traffic Server is a caching server with Drupal support. The incubating Apache OpenMeetings project has a module for Drupal integration too.

The Apache OpenOffice project itself maintains two old but functional Drupal sites for hosting its Extensions and Templates, that were recently relocated to SourceForge with technical advice from Nuvole; and sooner or later it will have to consider a deeper integration with Web technologies...

We at Nuvole are looking forward to exploring opportunities for cross-project collaboration, and the ApacheCon 2012 in Germany next month might be a nice occasion for brainstorming. If you have ideas to share, please do so in the comments below.

Sep 12 2012
Sep 12

After the successful experience from last June, Nuvole is proud to join again the Drupal Global Training Day initiative on September 14th.

This time we will hold the event in Parma, Italy, and, following the initiative guidelines, we will give a free generic introduction to Drupal, focusing on Drupal as a platform, its community, what can be easily done with the available modules and what can be reached with a bit (or a lot!) of customization.

Since there's nothing better than real use cases to show what Drupal can do, we will also show and discuss in detail some recent Nuvole projects. If you can't make it to Parma, here are the fact sheets, with screenshots and short texts in Italian, we prepared to describe our most interesting projects:

The event is free to attend, and attendees are also welcome to stay for a buffet lunch. Registration is required. Please see the registration page for all details.

Aug 24 2012
Aug 24

The DrupalCon Munich 2012 is just over. There were quite a few inspiring sessions, but here are a few highlights of the moments and topics where the Nuvole team was mostly involved.

Code-Driven Development: another training... and what about Drupal 8?

We held the pre-conference Nuvole training about Code-Driven Development (Features, Makefiles, a set of techniques for effective Drupal programming) at DrupalCon Europe for the first time, after two successful editions at DrupalCon Chicago 2011 and DrupalCon Denver 2012. Nice to see that there are more and more training attendees who are already familiar with the tools but still want to see the big picture and find out how to really streamline their Drupal development.

And what's coming with Drupal 8? We followed with great attention Greg Dunlap's Munich session to understand the impact of the Configuration Management Initiative on the Code-Driven workflow we advocate. There will surely be disruptive changes, but in the end Drupal will be improving a lot as far as configuration management is concerned. And Features won't die: part of its functionality (the import/export itself) will be taken over by Drupal core, but Features will be able to refocus as a tool to package configuration. And it's time for Nuvole too to stop lurking on the CMI group and start showing up more frequently on issue queues!

BoF: Automating Drupal Development

The BoF session about Automating Drupal Development was packed, as many developers shared their secrets to effective Drupal Development.

The basic idea was how to get rid of all repetitive tasks in Drupal Development and automate as much as possible: building the code base (Drush Make), creating the installation profile from templates, storing and packaging configuration with modular Features and a Features server, rely on an automated testing framework activated at every code change. Tools we discussed are mostly the same as in our Barcelona DrupalDays presentation, with the addition of Capistrano and Webistrano.

BoF: The future of Open Atrium: getting it done

The BoF about the future of Open Atrium was to bring together the core Open Atrium team, working for Phase2 Technology, and companies and consultants that, like Nuvole, provide Open Atrium services: if we wish to move from talk to action, multiple parties will need to help. Here's an outline:

  1. Update core and modules to their D7 version, update the Blog (to become "Discussion") and Book features, introduce the concept of "Organizations" to be able to apply certain criteria (e.g., inclusion in a group) to multiple users.
  2. Adopt a new, mobile-friendly, responsive, theme.
  3. Migrate the other Atrium features.

Development is expected to start soon with the creation of a Drupal 7 branch for all involved features. The basic Open Atrium structure will be ported to Drupal 7 as soon as possible, to give all community members the opportunity to help. A development version will be regularly made available for people to follow progress.

Lower priority items, which could appear after the Open Atrium 2.0 release (based on Drupal 7), like in version 2.1, include a full content migration path from OpenAtrium 1.x and adding new functionality. But the discussion is open and if you want to help shaping the future of Open Atrium just get involved!

Jul 27 2012
Jul 27

At Nuvole we have always supported the idea that Open Atrium can deal with complex use cases. Modules like Spaces, PURL and Organic groups can push the limit of the platform far beyond being a simple-yet-powerful intranet software. We were already experimenting with building public websites and simple distributions-like mini-sites with Open Atrium for quite some time, but now the new Alfa Puentes project gave us the opportunity to blend together all those customizations in one powerful platform.

These concepts will be covered in more detail in the Nuvole DrupalCon Munich Training.

The Alfa Puentes project's main aim is to enhance the international cooperation between the European and the Latino-American Higher Education environments by creating a community of teachers, rectors and other related stakeholders. The members of this community need to share data and information both online, using an intranet platform, and offline, by participating to a series of mid-size seminars and conference spread across the two interested regions. Given the diversity of this community, multi-language support was also a strong requirement.

The platform is organized in three main parts: a public portal, a series of private self-managed intranet groups and mini-sites for the organization of real-life events. Since it's developed on a single Open Atrium installation users of the platform can have different roles in each components, e.g., a rector can start a private discussion group while a project partner may help with translations.

The portal is based on our mini-site features set, it contains information about the project, like funding periods and partners involved. All content is available in three languages: English, Spanish and Portuguese. Site managers can easily assign content translation to partners or collaboratively work on a specific section of the website. Even though the portal is implemented as a specific Open Atrium group type, the site look and feel does not resemble in any way its default theme: visitors perceive the portal as being an independent site.

All portal content is available in three languages:

ap-multilanguage2.png

Even though it is built as a group the portal does contain highly customized sections:

ap-partners.png

In a cooperation project it is essential to provide a platform where users can easily engage in a conversation and share relevant information: nothing can be simpler with Open Atrium. Each partner can start a private discussion group and can easily invite users to participate. To facilitate information sharing each group can be powered with our Atrium Folders feature, which provides a more user friendly and familiar way of sharing documents and files than the built-in Notebook feature. The language of each group can be set at its creation, chosen among English, Spanish and Portuguese.

Group owners can invite users to join a group by using powerful search tools:

apinviteusers.png

Atrium Folders enhances the document sharing user experience:

apfolders.png

The mini-site features set also powers the creation and management of mini-sites for organization of events. Each event site is an independent Open Atrium public group, with a specific Spaces preset which, at every site creation, enables features like static pages, custom navigation menu pre-filled with default content, news section and a spotlight area on the front page. Each mini-site must also provide a customizable per-event registration form which will add specific information (like participation to dinners, workshops, etc...) to the usual user profile data. To implement such a functionality we have integrated the Webform module with Open Atrium, ensuring a smooth user experience in managing such a complex use case.

Managers can deploy and customize a fully fledged event website in minutes:

ap_conference.jpg

Users can integrate their profile with event-specific information:

apregistration3.png

The default Open Atrium user profile section has been customized to be the starting point for the user to find her way trough the system. After the login the user is redirected to her profile page, from where she can have direct access to update her personal information, get to the groups she is member of and manage her event registrations.

apuserdashboard.png

Jun 25 2012
Jun 25

Automating Drupal Development: Makefiles, Features and beyond

Andrea Pescetti

25 Jun 2012

1 Comment

Andrea Pescetti

25 Jun 2012

1 Comment

Andrea Pescetti, 25 Jun 2012 - 1 Comment

The Nuvole presentation at Drupal Dev Days Barcelona

Features are a well-known and very useful tool to streamline Drupal development and write reusable components. However, if you get serious about automating as much as possible in your Drupal development, you need to add other tools to your daily practices, and master them properly: forget the tedious, error-prone, point-and-click and embrace Code-Driven Development.

Automating Drupal Development, as presented by Nuvole at the Drupal Developer Days Barcelona last week, consists of the following steps:

  1. Automating code retrieval. Use Drush Make to keep track of modules, patches and Features, and rely on Buildkit as a basic distribution with preselected modules to make your development faster. Use Drush Bake to create makefiles based on templates.
  2. Automating installation. Customize the installation profile to perform all tasks you need during installation, especially pre-configuring your site with those "soft configuration" settings that the site administrator will be able to modify without overriding your Features.
  3. Automating site configuration. Use Features properly, to make them truly modular, and install a Features server, where you will host and track your Features.
  4. Automating tests. Use continuous integration to automatically ensure that your website will continue to work as expected when it is upgraded: test your codebase, installation and site configuration on every code change.

These concepts will be covered in more detail in the Nuvole DrupalCon Munich Training (if you don't see the page, you may need to register to the DrupalCon Munich website).

The full presentation from Barcelona is below, as a Slideshare embed or a PDF file (attached).

drupal_dev_days_bcn.pdf (13.94 MB)Download
Jun 05 2012
Jun 05

Drupal Global Training Day

Antonio De Marco

5 Jun 2012

3 Comments

Antonio De Marco

5 Jun 2012

3 Comments

Antonio De Marco, 5 Jun 2012 - 3 Comments

Nuvole organizes a free event for NGOs in Brussels

Nuvole is proud to join the Drupal Global Training Day on June 22nd.

We will give a free generic introduction to Drupal. So this won't be our usual, highly technical, training about streamlining Drupal Development that you may have seen at Drupalcon Chicago 2011, DrupalCon Denver 2012 and that is scheduled for DrupalCon Munich 2012 too. This time we will focus on Drupal as a platform, its community, what can be easily done with the available modules and what can be reached with a bit (or a lot!) of customization.

The target public is mainly people who would like to assess Drupal for use in international not-for-profit organizations: Nuvole has a long history of successful projects with this kind of organizations, and the examples we will show are all from this sector.

Topics will include:

  • A generic introduction to Drupal and its community
  • Why open-source is the best solution: low entry cost, availability of thousands of free modules, focus on customization
  • Drupal for distributed NGOs: Public websites with private working groups (Intranet) and file repositories
  • Drupal for event sites: minisites for conferences and events, easy to customize and replicate
  • Drupal for campaigns: high-impact sites for campaigns with social networks integration

The event is free to attend, and attendees are also welcome to stay for a buffet lunch. Registration is required. Please see the registration page for all details.

May 03 2012
May 03

Our review of Tracy Smith's Open Atrium book just made it to Slashdot, confirming there is a widespread interest in this popular Drupal distribution. (By the way, the book is not, and is not meant to be, useful to developers, but if you build Open Atrium projects you should definitely recommend it to your clients: it will save a lot of time to you and them).

The most interesting consideration is that the book, published in January 2011, is still perfectly current now, as of Open Atrium 1.3 released just a few weeks ago. And this is not quite good: most distributions have been significantly updated in recent months, while Open Atrium has been quite conservative in features and updates so far.

In case you haven't heard, this is going to change. The future of Open Atrium looks bright, and, while there isn't a roadmap yet, the guys at Phase2 have recently taken steps to make sure that Open Atrium can again be a shiny example of innovation and bleeding-edge, useful, technology:

  • The Open Atrium Development Group is now open for everybody to join. Open Atrium is now a true community product with a transparent development process.
  • A Feature and Theme Directory is now available to find in a single repository all features and themes created by the Community, such as Nuvole's Atrium Folders.
  • An interesting BoF session was held at DrupalCon Denver, where we shared our experience with advanced Open Atrium customizations and we discovered that people are pushing this distribution to many different use cases: there are hundreds of organizations and companies working with Open Atrium now, and each of them can provide valuable feedback in shaping the future version.

The discussion about Open Atrium on Drupal 7 is now open, don't miss it!

Feb 10 2012
Feb 10

New international projects, new office, and hiring!

Nuvole is going to add a couple of international projects and some advanced Open Atrium customization services for non-profit organizations to its portfolio in the coming months. And if you are a skilled Drupal Developer you can be involved too!

Our upcoming projects will require a stronger presence in Brussels, the place to be for every international organization in Europe. So, while still keeping our Italian headquarters and office unchanged, we've just expanded our Belgian office. The new office is located in ICAB, a modern business centre in Brussels close to the Flemish university: a place with a vibrant international student community, equipped with a gym, a swimming pool and pubs.

The new Brussels office was officially inaugurated with a reception last week (pictures below) and it will be the place where we meet with international clients and we develop the EU-funded projects Nuvole participates in, like:

  • Alfa Puentes (2011-2013): a three-year project for international cooperation between Latin America and Europe on educational matters.
  • Open Sounds: a Leonardo da Vinci project (2012-2013) for transnational cooperation in music production.
  • Higher Education Experts (2012-2013): a renewed version of our customized Open Atrium portal for European experts in Higher education.

Want to be involved? We welcome applications: if you are a skilled Drupal 6 and 7 developer, just see our job post and apply!

nuvole-opening-3.jpg

nuvole-opening-2.jpg

nuvole-opening-1.jpg

Feb 07 2012
Feb 07

An extract from the new teaching materials we are preparing for our DrupalCon Denver 2012 pre-conference training, Code-Driven Development: Use Features Effectively.

By now the advantages of a clean Code-Driven Development workflow are clear to the majority of Drupal developers; things like separation between configuration and content, packaging and deployment of new site functionalities or sharing changes in a distributed team don't look that scary anymore.

Still not everything in Drupal can be clearly classified into configuration or content, such as Taxonomy terms. Taxonomy terms are mostly used to categorize our content so, naturally, they are often used in site configuration: a context that reacts to a given taxonomy term is a fairly common scenario. Taxonomy terms can be generated by users (think about free-tagging), which makes them fall into the "Content realm". Drupal, in fact, considers them as such, assigning to each term a unique numeric identifier, and that's the problem.

Each component has its own name

One of the turning points in making configuration exportable in code was the introduction of a unique string identifier for each component: this way it's easy to share configuration and to avoid conflicts. So what happens with taxonomy terms? If they appear in our context conditions then we'd better bundle them together: no matter where we are going to deploy our feature, they will always have to have the same values. That's simply not possible: they have numeric IDs, forget about easy life here.

Various attempts have been made to export numerically identified components, such as UUID Features Integration or the handy Default Content module, but they only solve part of the problem: we want other components to know the unique name of our terms.

Hard and Soft configuration

At Nuvole we adopted the following terminology to classify the two kind of settings that we need to deal with everyday:

  • Hard configuration includes the settings under the distribution developer's control (e.g., Views or Contexts); it has a machine name, it is easy to export, it gives no headache. We store it in Features.
  • Soft configuration includes the settings that are meant to be overridden by the site administrator (e.g., the default theme, or the initial terms of a vocabulary); it often gets a unique numeric ID from Drupal, it is impossible to export safely, it is painful to handle. We store it in the Installation profile.

This distinction becomes fundamental when the configuration is altered or (if you are dealing with a distribution) when the underlying distribution is upgraded. In the case of Hard configuration, altering it results in an overridden feature, which is upgrade-unsafe. In the case of Soft configuration, altering it does not change the Features state, since the corresponding settings are stored in the Installation profile, and changes are upgrade-safe.

Not only taxonomy terms

The distinction between Hard and Soft configuration goes beyond how to conveniently export taxonomy terms: it is more a design decision, especially important when dealing with distributions. We consider everything that the site builder might be entitled to change as Soft configuration. The place where to usually store Soft configuration is your hook_install(); this guarantees a safe upgrade path to the next version of the distribution. An example could be the default theme: you may ship your distribution with a specific theme but the site owner might want to change it and subsequent updates shouldn't alter it.

Here is how our profile hook_install() might look like in a Drupal 7 distribution:

<?php/**

* Implements hook_install()
*/
function example_install() {
 
   $terms
= array();  
 
   $vocabulary
= taxonomy_vocabulary_machine_name_load('category');

 
   $terms
[] = 'Solution';
 
   $terms
[] = 'Client';
 
   $terms
[] = 'Use case';

 
  
foreach ($terms as $name) {
    
$term = new stdClass();
    
$term->vid = $vocabulary->vid;
    
$term->name = $name;
    
taxonomy_term_save($term);
   }
  
 
// Enable custom theme
 
 
theme_enable(array('example_theme'));
 
variable_set('theme_default', 'example_theme');  
}

?>

Reference for site builders

If you are customizing a distribution and you need to override some of its default Hard configuration you might want to have a look at the Features Override module and at these two related articles from Phase2 Technology:

Jan 18 2012
Jan 18

Nuvole built some respectably sized projects in 2011: a few large international projects (including a heavily customized Open Atrium installation for Higher Education experts and a portal for collaboration between Europe and Latin America on educational matters) and a bunch of ordinary websites, besides our other activities such as trainings and general consultancy. And people occasionally ask us how big Nuvole is.

Well, the truth is that Nuvole is a two-people company, helped by minor contributions by external consultants. Yet, it manages to run and maintain sizeable Drupal projects by using Features -the easy part- and by doing it properly - the hard part, and the main focus of our DrupalCon Denver Training.

So the key is not how many people work on a project, but how efficient their workflow is. Adopting a Features-based workflow provides a solid basis, but you still need to take a lot of design decisions: some will be easier, some will require a bit of thinking, some will prove correct or wrong only months later, when the project needs infrastructural updates.

Nuvole pioneered a Features-based development, and what in general we call the "Code-Driven Development workflow", a couple of years ago. Our Features-based projects look much different now: we found out that our old structure was not optimal, or that technology allowed for cleaner workflows (Drupal 7 brought some substantial improvements, for example). We structured our new projects to take the new knowledge into account, found new challenges and gradually solved them.

Here are a couple of examples of the design decisions you will be happy to have taken properly (we will cover them in detail in future blog posts).

Hard and soft configuration. A site, especially when built as a distribution, should ship with complete pre-configuration. And this pre-configuration should be in code, we don't want to carry a database around. But should all of it go into Features? No, because some pre-configuration (the soft one) is meant to be overridden in the normal site customization, while Features should only contain the hard one, i.e., configuration that defines the site structure. The soft configuration (like the default site title, or default colors) is best handled by putting the corresponding code in the installation profile rather than in Features.

Feature separation. When all your site configuration is in Features, you quickly realize that it is not feasible to put everything into one Feature: you will need multiple Features to build a website, and this means you will have to take decisions on how to split your site functionality across Features. A common mistake is to build transversal Features, like a "permissions" Feature with all site permissions: this works, but it introduces annoying interdependencies and maintenance difficulties in the long run. The problem is best solved by basing Features on content types, thus making them truly modular: in general, a Feature should contain a content type and everything that is related to it, such as views, contexts, image styles and permissions.

The Nuvole DrupalCon training, Code-driven Development: Use Features Effectively, will be held on March 19th, the day before DrupalCon Denver. The training is open to both DrupalCon attendees and externals, and must be booked from the DrupalCon registration page.

Nov 28 2011
Nov 28

A single Open Atrium installation to serve minisites from different domains with a common backend

You can use a single Open Atrium installation to create minisites, i.e., minimal websites with a simple structure, served at different domains, but sharing a centralized backend. Each minisite can be public or private and can have a specific theme and specific features. An anonymous visitor will only see a small, self-contained site, while site editors will be able to manage content on all minisites from the same backend.

This is an ideal situation, for example, when an Open Atrium installation is used as a private Intranet but you want to build small auxiliary sites for conferences or events, and possibly take advantage of the fact that editors and registered users are the same as the main Intranet.

And, best of all, this can be done with a minimal amount of coding and respecting the Open Atrium architecture.

Creating and Customizing a Minisite

Our aim is to build a feature that will allow us to create and customize a minisite in just a few minutes. We want to start from the ordinary "Create Group" page:

minisite-create.jpg

And this is what we get immediately upon form submission:

minisite-new-1.png

The minisite ships with default content (pages linked from the left side menu) and the editor can just click and add content.

We can also hook our minisite to the built-in look-and-feel customization that Open Atrium provides for its groups and give the possibility to the editor to choose background and foreground colors:

minisite-color.png

After a quick content editing, the editor can achieve something like this:

minisite-custom-1.png

Screenshots are taken from Alfa Puentes, an international project funded by the EU that will focus on exchanging best practices between Europe and Latin America about higher education and that will include several events and conferences, each with a dedicated minisite.

Let's now see how to build this feature in Open Atrium.

Creating a minisite group type (spaces preset)

To start, we simply define a new spaces preset type, named "minisite": this can be done through hook_spaces_presets() using the existing definitions for public and private spaces from atrium_groups.spaces.inc as a basis.

<?phpfunction atrium_minisite_spaces_presets() {
 
$export = array(); $spaces_presets = new stdClass;
 
$spaces_presets->disabled = FALSE;
 
$spaces_presets->api_version = 3;
 
$spaces_presets->name = 'minisite';
 
$spaces_presets->title = 'Minisite';
 
$spaces_presets->description = 'Minisite space preset.';
 
$spaces_presets->space_type = 'og';
   ...
?>

The new space preset can be exported into a feature and creating a minisite becomes as easy as creating a new group.

minisite-create.jpg

Assigning features to a minisite

Just like a standard Open Atrium group has some features available by default, we will want our minisites to use a certain set of features by default. In our case, we built two features for Pages and News and we enable them for our minisites, that will thus have static pages and news available.

<?php ... (follows from above) ...
 
$spaces_presets->value = array(
   
'variable' => array(
     
'spaces_features' => array(
       
'atrium_blog' => 1,
       
'atrium_book' => 0,
       
'atrium_calendar' => 1,
       
'atrium_casetracker' => 0,
       
'atrium_members' => 1,
       
'atrium_pages' => 1,
       
'atrium_shoutbox' => 0,
       
'spaces_dashboard' => 1,
       
'atrium_news' => 1,
      ),
  ... (continue
along the lines of atrium_groups.spaces.inc) ...
?>

Making minisites self-contained: menus and blocks

We want our minisites to be self-contained as much as possible. In order to achieve that, with some standard Drupal hooks, we create a new menu for each minisite, that takes care of updating it as soon as the respective minisite group changes. Here is one of the implemented hooks:

<?php
function atrium_minisite_nodeapi(&$node, $op, $arg = 0) {
 
  if (isset(
$node->spaces_preset_og) &&
     
atrium_minisite_is_minisite_preset($node->spaces_preset_og)) {
    if (
in_array($op, array('insert', 'update', 'delete'))) {
     
$menu = array();
     
$menu['title'] = $node->title;
     
$menu['menu_name'] = atrium_minisite_get_menu_name($node);
     
$menu['description'] = $node->og_description;
     
atrium_minisite_menu_api($op, $menu);
     
      if (
$op == 'insert') {
       
module_invoke_all('atrium_minisite_default_content', $node, $menu);
      }
    }
  } 
}
?>

As you can notice, our minisite feature exposes an atrium_minisite_default_content() hook which allows other modules to provide default content once a new minisite is created (e.g. "About" and "Contact" pages, etc...). Shipping each new minisite with default content allows the editor to start filling up the site straight away without the need to recreate again and again the same content structure.

To make our minisite menu group-aware, we implement hook_block() in atrium_minisites.module. The implementation below relies on a couple of helper functions defined elsewhere.

<?php
function atrium_minisite_block($op = 'list', $delta = NULL, $edit = NULL) {
 
 
$blocks = array();
  if (
$op == 'list') {
   
$blocks['primary-navigation']['info'] = t('Minisite: Primary navigation');
   
$blocks['primary-navigation']['cache'] = BLOCK_NO_CACHE; $blocks['secondary-navigation']['info'] = t('Minisite: Secondary navigation');
   
$blocks['secondary-navigation']['cache'] = BLOCK_NO_CACHE; $blocks['full-navigation']['info'] = t('Minisite: Full navigation');
   
$blocks['full-navigation']['cache'] = BLOCK_NO_CACHE;
  }
  if (
$op == 'view') {
    if (
atrium_minisite_is_minisite_space()) {
     
$config = atrium_minisite_get_menu_block_config($delta);
      if (
$delta == 'secondary-navigation' || $delta == 'full-navigation') {
       
$config['level'] = 2;       
       
$config['expanded'] = 1;
       
$config['depth'] = 0;
      }
      if (
$delta == 'full-navigation') {
       
$config['level'] = 1;       
      }
     
$blocks = menu_tree_build($config);
      unset(
$blocks['subject']);
    }
  }
  return
$blocks;
}
?>

This block is then specified as a context reaction, so that site visitors will see a self-contained navigation when browsing the minisite.

Making minisites themeable

Each minisite can be assigned a different theme. To do so from a convenient interface, we implement hook_form_alter() in atrium_minisite.module to give the possibility to select a theme for the given minisite. Again, we omit some helper functions for brevity.

<?php
/**
* Implementation of hook_form_alter()
*/
function atrium_minisite_form_alter(&$form, &$form_state, $form_id) {
 
  if (isset(
$form['#node']) && $form_id == $form['#node']->type .'_node_form') {
   
$node = $form['#node'];   
   
    if (
og_is_group_type($node->type)) {
     
module_load_include('inc', 'system', 'system.admin');     
     
atrium_minisite_theme_form($form);
    }
   
    if (
atrium_minisite_is_minisite_space()) {
      if (
$node->type == 'page') {
       
$space = spaces_get_space();
       
$conf['menu_default_node_menu'] = atrium_minisite_get_menu_name($space->group);
       
$menu_name = atrium_minisite_get_menu_name($space->group);
       
$menu = array($menu_name => $space->group->title);
       
$form['menu']['parent']['#options'] = menu_parent_options($menu, $item);
      }
    }
  }
}
?>

We can now choose the best theme for our minisite directly on the creation page:

minisite-theme.jpg

Serving minisites on different domains

Each Open Atrium group gets its own URL path component; in our case the minisite will be reachable at something like http://alfapuentes.org/conference/. With a quick Persistent URL customization we can actually set the URL rewriting to be per domain, allowing our minisite to have its own domain. This can be achieved by:

  1. Enabling the "Domain" URL modification type from admin/settings/purl/types;
  2. Assigning to "Group space" the new modifier type on admin/settings/purl;
  3. Adding a custom URL each time we are going to create a minisite group

By taking advantage of the Persistent URL domain rewriting we can really make the new minisite look completely independent from the underlying Open Atrium platform:

minisite-url.png

The techniques shown here are covered in detail in our trainings; if interested, contact us for more information.

Aug 24 2011
Aug 24

Building and Maintaining Drupal Distributions

Andrea Pescetti

24 Aug 2011

6 Comments

Andrea Pescetti

24 Aug 2011

6 Comments

Andrea Pescetti, 24 Aug 2011 - 6 Comments

Our presentation at DrupalCon London 2011

Our DrupalCon London 2011 presentation Building and Maintaining a Distribution in Drupal 7 with Features can be found as a Slideshare embed below; you can also find the final slides in PDF format on the session page on the DrupalCon site or attached to this post.

For further resources, you can refer to the code-driven development posts in the Nuvole blog or check out our trainings (next: London in October). And for those who couldn't get a printed copy of our code-driven development cheatsheet, a PDF version is here.

nuvole-drupalcon-london-2011.pdf (13.33 MB)Download
May 25 2011
May 25

Open Atrium's default set of features covers most of the common needs of an average organization, except one: a file repository with the familiar look and feel of a folders tree. By deploying customized versions of Open Atrium for different kinds of organizations we noticed that the built-in Notebook feature is still cumbersome for intranet users to store and categorize their documents (meeting reports, minutes, etc...): they are used to store their files in directories and subdirectories and not as books and child pages.

On the other hand, the needed technology for a more familiar documents repository is there: Drupal's core Book module can create hierarchical relations among nodes and files can be easily attached to nodes, so it's enough to interpret book pages as folders and their attachments as files to get the same paradigm users are familiar with.

Enter Atrium Folders: A simple file repository application

The idea behind Atrium Folders is to have a very simple file repository application with no external dependencies that users can just download, enable and start playing with. To get started, download the code directly from Nuvole's GitHub, place it under sites/all/modules/features in your Open Atrium installation and enable the new feature. Atrium Folders is shipped as an ordinary Drupal feature so, after enabling it as a module, we need to enable it in the Open Atrium group.

folders-settings.jpg

We can now visit the new Folders section and start adding the first folder.

folders-add-folder.jpg

As already mentioned, folders are nodes: we just need to specify its name, press Save and we are good to go. Now, say goodbye to the ordinary Drupal node interface; from now on we will be managing our repository from an intuitive "filesystem browser"-like interface:

folders-overview.jpg

Managing your repository

Use the top menu to manage the folder currently being displayed; it contains the following four items.

Basic information: change name and description of the current folder:

folders-generalinfo.jpg

Subfolders: easily add a bunch of subfolders by entering their names, one per line:

folders-subfolders.jpg

Attach files to this folder: just the reinterpretation of the good old Drupal file upload form, it gives the possibility to upload as many files as we need to the current folder:

folders-upload.jpg

Notifications: specify who will get a notification of the current changes (again, we don't reinvent the wheel but we integrate with the default Open Atrium notifications system):

folders-notifications.jpg

Upload multiple files: quickly upload a ZIP archive containing several files and folders: Atrium Folders will unzip it for you and place its content in the current folder (PHP must have ZIP support enabled in order for this functionality to be available)

folders-zip.jpg

Rearranging folders

The Reorder tab allows to rearrange the structure of our repository by simple drag-and-drop. This handy interface, borrowed from Drupal's core Book module, is also very helpful when we have to rename several folders at once.

folders-reorder.jpg

File toolbox

Each file has a toolbox that will allow to rename, move or delete the respective file. The toolbox uses jQuery and AJAX calls extensively, to guarantee a smooth user interaction: files will be modified and changes will take immediate effect, with no need to reload the page.

folders-toolbox-rename.jpg

Creating your own toolbox

Atrium Folders exposes hook_folder_toolbox() to enable third party modules to expose their own toolbox. As an example, here is the default atrium_folders_folder_toolbox() implementation:

<?php/**
* Implementation of hook_folder_toolbox()
*/
function atrium_folders_folder_toolbox() {
  return array(
    array(
'op' => 'move',
     
'type' => 'file',
     
'title' => t('Move'),
     
'description' => t('Move the file to another location.'),
     
'form callback' => 'atrium_folders_move_file',
     
'ajax callback' => 'atrium_folders_move_file_ajax_callback',
    ),
    ...
  );
}
?>

Drag and Drop Upload

Atrium Folders ships with a built-in integration for the Drag'n'Drop Uploads module which gives the possibility to simply drag and drop files on the upload form to attach them to a node. If Drag'n'Drop Uploads module is enabled a Drop zone will be visible in the Attach files to this folder panel.

folders-dropzone.jpg

Drush integration: import an existing structure

When an organization wants to switch to Open Atrium, in most cases they need to migrate a shared folder to the new intranet. Atrium Folders includes the folder-import Drush command that allows to import a directory located in our local filesystem into a certain folder of a specific Open Atrium group. We just need to specify the full path of the directory we want to import and the Drupal path of the group we want it to be imported:

$ drush folder-import /tmp/meeting secretariat
Created 13 folders and 168 files.

Type $ drush help folder-import for more.

Apr 12 2011
Apr 12

Drupal Solutions for Public Works Monitoring and Remote Collaboration

Antonio De Marco

12 Apr 2011

4 Comments

Antonio De Marco

12 Apr 2011

4 Comments

Antonio De Marco, 12 Apr 2011 - 4 Comments

Our presentations from Drupal Government Days Brussels

The Drupal Government Days held last week in Brussels were a good occasion to showcase two solutions by Nuvole, born as services for local and European institutions.

Public Works Monitoring in Drupal

Nuvole built a dedicated platform, based on the widely used Drupal system, to make it easy for municipalities to monitor public works in real time and optionally share selected information with citizens.

Please find the Slideshare embed below.

Remote Collaboration and Institutional Intranet

Nuvole created a solution for the European Commission based on Drupal and Open Atrium to allow several hundreds experts to discuss in a Virtual Community about the harmonization of higher education in Europe. Besides the Virtual Community, several websites are created for the periodical seminars, all based on a common template and single sign-on.

Please find the Slideshare embed below.

Mar 25 2011
Mar 25

Our Code-Driven Development with Features training in Chicago was a very interesting experience for us: people with different levels of Drupal expertise were able to appreciate the benefits of code-driven development and the most experienced attendees managed to experiment with the development workflow on their own laptops, by building and modifying sandbox websites.

5507028473_f9ca241a3a_b.jpg

As a gift to those who couldn't attend the training because it was sold out, and to all lovers of Drush, Features and code-driven development in general, we are sharing a Code-Driven Development Cheatsheet that was part of the training materials. Please find it attached to this post, in PDF format.

cheatsheet.png

We still have some printed copies available to give away; if you are attending the Drupal Government Days in two weeks in Brussels and are interested in one just let us know.

Thanks to the DrupalCon trainees for their nice and constructive feedback, to DrupalCon organizers for assistance and logistics... and for those who couldn't make it to Chicago, there will be further opportunities in Europe in the next months!

Image credits: from DrupalCon Chicago on Flickr.

Feb 07 2011
Feb 07

Open Atrium, Beyond the Intranet

Antonio De Marco

7 Feb 2011

13 Comments

Antonio De Marco

7 Feb 2011

13 Comments

Antonio De Marco, 7 Feb 2011 - 13 Comments

A new way to look at Open Atrium - From the Brussels Drupal Dev Days

Open Atrium is designed to be a powerful Drupal-based Intranet solution, but the underlying technology allows to do much more: creating a public portal with a totally different graphic design and complementing it with a private Intranet; creating other group presets than the default "public" and "private" group; customizing the profile fields in a clean and modular way, and several other possibilities.

Here is the Nuvole presentation from the Drupal Dev Days in Brussels (Slideshare embed below, PDF attached to this post).

If you are interested in discussing Open Atrium from a developer's point of view at DrupalCon Chicago next month, please join the BOF.

Pages

About Drupal Sun

Drupal Sun is an Evolving Web project. It allows you to:

  • Do full-text search on all the articles in Drupal Planet (thanks to Apache Solr)
  • Facet based on tags, author, or feed
  • Flip through articles quickly (with j/k or arrow keys) to find what you're interested in
  • View the entire article text inline, or in the context of the site where it was created

See the blog post at Evolving Web

Evolving Web