Skip to Content

Planet Drupal

Syndicate content - aggregated feeds in category Planet Drupal
Updated: 1 day 23 hours ago

Four Kitchens: The Great Consolidation - migration case study presentation

9 March 2015 - 12:37pm

At 1am Pacific on January 29th, 2015, Entertainment Weekly quietly switched to Drupal 7. Ten WordPress VIP blogs and a monolithic Vignette V6 Content Suite were deprecated. Over a half million articles and images were migrated to a new design and modern publishing platform, and Four Kitchens led the development.

On February 27th, 2015, three of the web chefs on the project presented a migration case study to a full room at SANDcamp 2015. Myself, Matt and Patrick fielded questions about the project. While no recording was available, I’d like to share the presentation with you.

Projects Development Drupal Events
Categories: Drupal

Drupal Association News: Voting is Open for the 2015 At-Large Board Elections

9 March 2015 - 8:13am

Voting is now open for the 2015 At-Large Board positions for the Drupal Association! If you haven't yet, check out the candidate profiles and review the Meet the Candidate sessions (we ran three) that we held. Get to know your candidates, and then get ready vote.

Cast Your Vote!

How does voting work? Voting is open to all individuals who have a account by the time nominations open and who have logged in at least once in the past year. These individuals' accounts will be added to the voters list on and they will have access to the voting.

To vote, you will rank candidates in order of your preference (1st, 2nd, 3rd, etc.). The results will be calculated using an "instant runoff" method. For an accessible explanation of how instant runoff vote tabulation works, see the this video.

Elections will be held from 9 March through 20 March (midnight UTC) 2015. During this period, you can still review and comment on candidate profiles.

Have questions? Contact Drupal Association Executive Director Holly Ross.

Categories: Drupal

Wuinfo: Easy Way Out Before Lost inside Views Maze

9 March 2015 - 5:30am

As I have talked in my previous blog about importing large quantity of node without feeds module. Today, I will show you how to build complicated block views without using views module.

Did you have ever faced the situation that views can not solve the problem? I have a unique request from my client this week. We need to have a related video block for video node page. There are three levels of sorting. First show the episode videos from the same series. Then show the videos having same tag. At last, show the rest of the videos that are not in the same series and have no tags in common. What are those three requirements really means? We need to sort all video nodes according to current node's taxonomy tags. So, views block is not the solution since we select all the nodes. Even though, views is one of the most used modules among Drupal websites; it is not a medicine for everything. As a rule of thumb, if any problem can not solved by one SQL query, then we should look for a solution in other places. The problem we are solving is related to complicated sorting that views can not do it. It is one of the case.

It took me and another Drupal developer all most two days to make a view on it. We can not find a good way to sort them. In the end, we give up views and decide to make a custom module for it. Within couple hours, a customized block was built. I found that a custom block was easier to build. It is more efficient than the views block. Here I would like to show you how does it work.

There are three parts of the module. First, get a list of the nodes. Second, render the list of the nodes. Third part is using the ajax framework to add the load more button.

Most difficult part of the module is to get the list of the nodes. Since all the request of 3 levels of sort are all done with the list of nodes. It is where views is not able to accomplish it. But it is more related to the business logic. Different project may face different logic. There is one thing I want to mention on this part. We need to be careful when build query. We are adding more and more videos to the website. Try to avoid loading too many videos into memory will be the key point to make sure the system will running smoothly after the site grow big. Check blog "build website with a million nodes" for more detail on it.

Here are the codes for the rest of 2 parts.

Render the list of nodes into a block. We use node teaser displays for each node in the block.

* Render the list of nodes into HTML.
function related_videos_render_json($count = 7, $position = 0, $cur_nid = 0) {
  $nodes = related_videos_get_list($count, $position, $cur_nid);
  $nid = array();
  foreach ($nodes as $key => $node) {
    $nids[] = $node->nid;
  if (!empty($nids)) {
    if ($count > count($nids)) {
      $count = 0;
    $nodes = node_load_multiple($nids);
    $build = node_view_multiple($nodes);
    if ($count != 0) {
      $build['loadmore'] = array(
        '#prefix' => '<ul id="related_videos_link" class="load-more"><li>',
        '#suffix' => '</li></ul>',
        '#type' => 'link',
        '#title' => 'Load More',
        '#href' => 'related_videos/nojs/' . $count . '/' . ($position + $count) . '/' . $cur_nid,
        '#id' => 'videos_ajax_link',
        '#options' => array('attributes' => array('class' => array('use-ajax'))),
        '#ajax' => array(
          'wrapper' => 'related_videos_link',
          'method' => 'json',
  else {
    $build['no_content'] = array(
      '#prefix' => '<p>',
      '#markup' => t('There is currently no content.'),
      '#suffix' => '</p>',
  return render($build);

The function related_videos_get_list($count, $position, $cur_nid) is to get the list of node where we put our node sorting logic there.

Then we use two block hooks to create a block for the list of video.

* Implements hook_block_info().
function related_videos_block_info() {
  $blocks['related_videos_block'] = array(
    'info'    => t('Related videos block'),
    'cache' => DRUPAL_NO_CACHE,
  return $blocks;

* Implements hook_block_view().
function related_videos_block_view($delta = '') {
  switch ($delta) {
    case 'related_videos_block':
      $cur = related_videos_current_node();
      drupal_add_library('system', 'drupal.ajax');
      $block['subject'] = t("Related Videos");
      $block['content'] = '<section class="col-xs-12 col-sm-8 wv-contnet video-related-wrapper"><h2>Related Videos</h2>';
      $block['content'] .= related_videos_render_json(7, 0, $cur->nid);
      $block['content'] .= '</section>';
  return $block;

So, now we have a block can be assign to anywhere with Drupal block system, panel or context module.

The last part is to use Drupal Ajax framework to add a load more button. We load more videos without reload the page.

First, implements the hook_menu to define the callback link for ajax request.

* Implements hook_menu().
function related_videos_menu() {
  $items = array();
  $items['related_videos/ajax'] = array(
    'page callback' => 'related_videos_ajax',
    'access callback' => 'user_access',
    'delivery callback' => 'ajax_deliver',
    'access arguments' => array('access content'),
    'type' => MENU_CALLBACK,
  $items['related_videos/nojs'] = array(
    'page callback' => 'related_videos_nojs',
    'access callback' => 'user_access',
    'access arguments' => array('access content'),
    'type' => MENU_CALLBACK,
  return $items;

The second menu item items['related_videos/nojs'] is for the fall back of browser have javascript disabled. For more detail, check Ajax framework document.

Then we build the callback function related_videos_ajax. We use the callback function in the implementation of hook_menu.

* Ajax callback for related videos content.
function related_videos_ajax($count, $position, $cur) {
  $data = related_videos_render_json($count, $position, $cur);
  $commands = array();

  $commands[] = ajax_command_replace('#related_videos_ajax_link', $data);
  $page = array('#type' => 'ajax', '#commands' => $commands);
  return $page;

The function related_videos_render_json is the function we used to render the HTML. We use the same function for the initial block content. Here, we got the HTML of the list of the node and delivered to the browser in JSON format for the load more button. The parameters $count, $position, $cur was passed in from the URL. The URL of the load more link is defined by the related_videos_render_json function.

Those three parts formed a custom block display a uniquely ordered video nodes. Use the powerful Drupal theme function and Ajax framework, it is easy to build a block like this.

Categories: Drupal

Josh Taylor: Automatically testing contrib modules when 8.0.x updates

9 March 2015 - 5:16am

Many 8.0.x contrib modules are being developed on Github, due to the flexibility it offers whilst 8.0.x is being developed.

As the complexity of 8.0.x has grown, needing to test modules using Continuous Integration (CI) is critical. offers CI for modules, but we need custom steps each build.

For example, to build commerce 2.x the following steps are required:

  1. drush si –db-url=mysql://root:@ –account-name=admin –account-pass=admin – –site-name=”Commerce” –yes
  2. drush en -y composer_manager simpletest
  3. drush composer-manager-init
  4. cd core
  5. rm -rf vendor
  6. composer drupal-rebuild
  7. composer update –prefer-source -n –verbose
  8. cd ..
  9. drush en -y commerce commerce_product commerce_order
  10. php core/scripts/ –verbose –color –concurrency 4 –php `which php` –url http://localhost “commerce” | tee /tmp/test.txt; TEST_EXIT=${PIPESTATUS[0]}; echo $TEST_EXIT

As you can see, quite a few commands are needed. For the full command list, check out the .travis.yml file commerce uses.


So what exactly is Travis? Well, wikipedia says:

Travis CI is an open-source hosted, distributed continuous integration service used to build and test projects hosted at GitHub. Travis CI is configured by adding a file named .travis.yml, which is a YAML format text file, to the root directory of the GitHub repository.

Similar to, everytime a new Pull Request is added on, it is tested against Travis to make sure everything passes.

This is all fine and dandy, but what happens whenever 8.0.x updates? 8.0.x can update many times a day thanks to the tireless work of the contributors and core committers, and change records come in thick and fast with breaking changes often happening.

Travis doesn’t offer a feature to do new builds via API out of the box unfortunately, however there is a script called “travis-cron” which is a shell command to trigger rebuilding the latest build of a certain branch, so I use this to rebuild the 8.x-2.x branch of Drupal Commerce, as only merges are done on this branch.

To get this to work, I use an opensource tool called Huginn, which is very similar to IFTTT. IFTTT basically means “If this, than that”, so you can perform an action whenever something happens.

I use Huginn for this, because IFTTT doesn’t have Webhooks yet, and I also need to run a bash command anyway, so hosting on a small VPS ($5/month) is worthwhile.

The first thing we want to do is enable the RSS agent, which will allow us to know whenever core has updated. This can be found as a link on the Core Commits page, with the direct RSS link being here.

To create a new RSS agent in Huginn, click “Agents -> New Agent”

From here, you can add all the settings you need, such as the URL to parse, how often to check the RSS feed (I have mine set to every 5 minutes)

After this is done, we need to setup another Agent, that will react on whenever a feed item is added. Since we want to react on all feed changes, not just certain items, this is easy to do, just adding a ShellCommandAgent will do the trick. You can use “travis-cron” to do this, reacting on the “Drupal Core Updates” RSS item.

Now whenever core has updated, travis-ci will rebuild the branch you have chosen with travis-cron!

Categories: Drupal

Liran Tal's Enginx: Apache Obfuscation by disabling trace and server tokens

8 March 2015 - 11:40pm

Apache Obfuscation can be achieved very easily and the benefits are great – it doesn’t disclose server information such as versions, OS, and does output verbose errors when ‘bad things happen’, and they happen.

Edit apache configuration, usually available here for RedHat based distributions: /etc/httpd/conf/httpd.conf

Make sure the following settings are present, save, and restart apache:

TraceEnable Off
ServerSignature Off
ServerTokens Prod
How do we test that this is actually working?

How to TraceEnable:
1. curl -v -X TRACE http://…
2. Confirm you get a forbidden response

How test ServerTokens:
1. Make a request to the website and check the response headers
2. Confirm the response contains only “Apache” information in the Server header

How to test ServerSignature:
1. Make a request to the website for a URL that should respond with Apache server error
2. Confirm you don’t see information about the apache server software version, OS, etc.


(adsbygoogle = window.adsbygoogle || []).push({});

The post Apache Obfuscation by disabling trace and server tokens appeared first on Liran Tal's Enginx.

Categories: Drupal How we built a Drupal distribution for the Estonian Government, part 2 – functionality highlights

8 March 2015 - 12:42pm

A while back I wrote the Part I of how we built the Estonian Government web platform. I had all the intentions to quickly follow that up with Part 2 and 3, but as always, things got busy. The good news is, however, that all the sites are now live for several months and I can use live examples to illustrate my text here.

Part II is about some of the functionality we built and the technical solutions used for it. The development phase lasted throughout the second half of 2013 and first months of 2014 – 7 months of development means a lot of different stuff was built. Instead of trying to cover it all, I will try to focus on the parts that I feel characterize this project the best.

I already wrote about how we implemented the Google Site Search for the Government platform, which definitely was one of the big and complex parts of the project. But yet another big one was…

Integration with centralized state personnel database

Estonian Government is keeping the contact information of its employees – that is, the ministers, officials, department personnel, etc. – in a unified information system, based on SAP technologies. That is a good thing, as theoretically only a single integration is needed to show the public contact details of those people on the Government web platform sites. There was a lot of value there – over the 14 sites, that’s thousands of people, whose contact details, positions and careers within their organizations are in constant change, and keeping that information up to date would be a huge task for a lot of web editors. Instead, we were aiming to get all that data from internal systems, where it was kept up to date anyway.

But there were problems:

  1. Different organizations had different hierarchies – ie., Government Office had two levels of departments, while the Ministry of Economics had 4 levels.
  2. The SAP database did not contain or could not export all the information that was required to be displayed in the web.
  3. Different Ministries had slightly different practices about how they stored the contact information in the data fields, so there were a lot of exceptions of what could be directly presented to the public and what needed manual sanitation to get a more or less unified picture across all the Ministries.

The field lock checkboxes on Contact node edit page

It was clear quite fast that there were too many exceptions and some of those could not be predicted with 100% accuracy. So we needed some sort of a combination of having 95% of contacts automatically imported, but having the possibility to manually override – and making sure that manual work can be switched back to automatic or vice versa if needed.

The technical solution was to build a “field lock” functionality. A Feeds import made a daily automatic import that created or updated Contact nodes. Each node contained about 10 different fields of data for a person, such as Name, Position, Department, Education etc. If any of those fields needed manual adjustments, the editor could do so, and then use a special checkbox for that field to lock it from automatic overrides – so that when the next automatic import happened the next day, that field was not overwritten. If the data was later corrected in the backend SAP system, the lock could be removed and Feeds would resume writing into that field.

Examples of the views displaying those semi-automatic Contacts can be seen here and here.

WYSIWYG content templates

Government sites contain a lot of content, and it can get quite overwhelming for a visitor who needs to go through and get a sense of several topics fast. So the Government Office wanted each content page to be something more than just a wall of text, to have more structure, sections, visual data and differentiation. We needed a tool that would help content editors craft pages like that themselves, without having to learn HTML and CSS for many months.

So we used the Wysiwyg API template plugin module to add a template selector functionality for CKEditor. Our frontend wizard Hannes pre-baked some 10-15 nice content templates, and content editors only had to select the correct one from a popup, replace the dummy text, and enjoy a professional-looking, rich content experience. Content templates were WCAG 2.0 AA level compatible, fully responsive, and could even be used inside one another.

Template selector popup within CKEditor


Here are some examples of pages (in beautiful Estonian) made by content editors who probably didn’t have to write a single line of CSS: Ministry of Economic Affairs and Communications is writing about energetics, Ministry of Culture describes how they use foreign resources, Government Office introduces Estonian Presidency of the Council
of the European Union 2018.

Aggregating content between the sites

One goal of the Government platform was to unify the content across different Ministries. This included several behind-the-scenes processes, but also a technical solution to aggregate content across different sites into one central source.

Each Ministry had their own page for news, weekly schedule, and contacts. These in turn had RSS feed outputs, like this and this, which could be used for news readers, open data initiatives and other machine-reading purposes, and also for aggregation.

The central information source and aggregator was to be (translated,, which was also running on the Government platform and didn’t represent any physical institution per se, but the government as a whole. So weekly schedule, news, and contact search pages on the site would display content from all the Ministries, pulled in over RSS. You can see “Source” filters there, in case someone would need to focus on content from just a few of the Ministries.

Unfortunately, the RSS export-import has not yet been configured for all the sites and therefore there is no active aggregation yet – I’m planning to write more about the woes of deploying 13 big sites and the importance of follow-up phases in Part 3 of this series.

Tagged: case study, Drupal 7, integrations, planet drupal
Categories: Drupal

Drupal for Government: 3d Printing Drupal Commerce Profile with Profiler Builder

8 March 2015 - 9:33am

We're almost ready to release the site - not all of the features are working right now - I'm having some trouble with conversions of STL files in to the correct units.. PITA, but the Rules module and Joe Pontani have made the process a lot simpler = thanks Joe!  As part of the release we're putting the code up in github, and we're now using Profiler Builder to facilitate distribution = thanks btopro :)  we're also using it with the distribution... thanks for the feedback on github to improve this aspect of the work.  The first bit about profile builder is adding libraries, patches, and even the variable table to the profile.

Categories: Drupal

Code Karate: Building a Dynamic display block with Minipanels

7 March 2015 - 10:19pm
Episode Number: 196

Sometimes you need to display something dynamically based on the page the user is currently viewing. Sure you can accomplish some of this with blocks, or even just panels, but sometimes it's nice to have the best of both worlds.

Tags: DrupalPanelsDrupal 7Layout ToolsSite BuildingDrupal Planet
Categories: Drupal

about seo