Benchmarks for the Display Suite module

I've been promising benchmarks for the Display Suite module after every presentation I gave so far. It took me a while to get a good setup but now it's here. I've used the demo site as a start, so there are a lot of modules enabled for this test. Views, panels, fivestar, heartbeat, comment, taxonomy, location, gmap, imagecache are the most important ones since they all integrate with the ecosphere of Display Suite modules.

I added a new content type called 'benchmark' and added 14 CCK fields to it: 4 textfields, 4 textareas, 2 images, 2 filefields, 1 node reference and 1 user reference. It also has a title, body, 2 taxonomy fields, a fivestar widget and a couple of comments.

Depending on the test, the complete set of modules integrating with Display suite are enabled or disabled. These include ds, ds_ui, cd, hds, nd, nd_cck, nd_search, nd_fivestar, nd_location, nd_switch_bm, ucd, ud and vd. You gotta love small project names right ?

Recent comments

Recent images

Horsegame
Horsegame
3 days 18 hours ago
Electricity people
Electricity people
3 weeks 2 days ago
Sunset boat
Sunset boat
5 weeks 5 days ago

Recent d.o. activity

Sweaver: a visual interface for tweaking your Drupal 6 theme

For the upcoming release of Conimbo, a Drupal distribution we're building at One Agency, we needed an easy and attractive way to theme your website without knowing anything of CSS. Having the opportunity to experiment once and a while during our free day at work, one of our colleagues started playing around with jQuery and manipulating the properties directly on the frontend - much like the Themebuilder created by Drupal Gardens, which he used as inspiration. After a while, I joined the coding part and sweaver was born - if you really want to know where the name comes from, that's all explained on Drupal.org.

Writing sweaver was interesting because of three reasons:

  • jQuery: we now probably know the jQuery manual by heart since we've had to look up a lot of new tricks to manipulate all kinds of stuff: iterating through all parents of a css selector, show/hide/close/open tabs and sliders, find out out the type of a selector and keeping it all manageable in a nice interface. It's been a tremendous ride so far and I'm pretty sure we've not reached the end of it.
  • CTools: sweaver uses the CTools plugins and exportables functionality. This means developers heaven both for us as maintainers, but also for other drupal people out there wanting to write their own plugin for this module. We're still into beta phase right now, so we might even use other functionality like object caching, Ajax and form tools.
  • Themes: we've learned that creating a re-usable theme isn't that easy, which is not even related to Drupal. Technology like cufon is fun, but clashed with our module. Switching to @font-face was something we've planned, but now got implemented faster. And I personally learned a lot of cool css tricks, but I'll stick with coding though :)

Interested and want to see how it looks like ? You can watch two video's we've created: a basic introduction and another where we show you how I've used the module to rebuild my own website. There is also a demo site where you can login and play around with it - not all plugins are enabled, but you should be able to create beautiful themes or hideous creatures :)

Downloads and more documentation is available on the project page on Drupal.org. It's important to know that we're still in development, so there are things that still act funky and might change completely during commits before a first release. Happy theming!

URL aliases: racing conditions and existing directories

Creating URL aliases on a Drupal site is a piece of cake. Core path in combination with pathauto and token modules are a real winner. However, there are some annoying cases which you should look out for because they can lead to painfull debugging sessions - especially when you've already encountered them in the past but totally forgot those. So for myself and all of you out there, here are 2 - in some way funny - URL alias pitfalls.

1. Existing directories

When you download Drupal and look at the root folder, you see a couple of subfolders like 'misc', 'sites', 'includes' etc. After installing, go to example.com/sites and you'll get the 403 forbidden page served by Apache (I assume the same happens on other webservers). This means you can't actually create an URL alias for a node (or a view, etc ..) called 'sites' or any of those other subfolders. The .htaccess will not rewrite to index.php?q= to lookup an existing path in your Drupal site or throw a 404 in case it doesn't exist. I've been experimenting with rewrite rules and while following code in the .htaccess will process the request for 'sites', do not use this in production because other http requests for images, javascript and css files in the sites/*/ folders will fail.

  # Again, don't use this in production!
  RewriteCond %{REQUEST_URI} "/sites/"
  RewriteRule ^(.*)$ index.php?q=$1 [L,QSA]

I gave up after a while - needed to solve this for a client - and simply renamed the URL alias for now. If anyone has a better idea, please let us know in the issue on d.o dedicated to this problem.

2. Racing conditions

This is really easy to reproduce: install the views module and enable the default frontpage view. Surf to example.com/frontpage and you'll get a list of all nodes promoted to frontpage. Now create a node and fill in 'frontpage' as the URL alias. You will be redirected to example.com/frontpage and you'll see your node instead of the view you have just enabled and there is absolutely no way to get back to that view unless you rename the alias of the node you've just created. This behaviour is very normal if you look at the code of drupal_lookup_path which is called by drupal_init_path in the bootstrap trying to rewrite the $_GET['q'] variable before menu_execute_active_handler() can find a path in the menu_router table. As with my first case, I simply had to rename the URL alias again to get my view back.

Any other pitfalls people know of ? Let me know!

Block caching with pagers

Drupal 6 and future core versions come with block caching. There are several constants you can set to determine how it is cached from none to per page, per role etc which then can hugely improve the performance on your site for both anonymous and authenticated users. But the cache also needs to be rebuild when there has been a total wipe of the page and block cache. Per page caching is an interesting one, but in some use cases leads to a lot of entries which you sometimes don't need.

An example: with faceted search (either with Apache Solr or with the Faceted search module), you can put a block in a sidebar giving you a list of facets to browse through results. Setting caching per page makes sense because the block contents will change depending on the facet you have clicked on. However, what with pagers ? The block will always have the same facet list, but will have a cache entry for each block because request_uri() will be different. We can avoid that one by having our own logic in a custom block.

This implementation exposes a new block and we deliberately set the cache to BLOCK_NO_CACHE because we will do our own logic in the function that will return the content of the block.

<?php
/**
* Implementation of hook_block().
*/
function test_block($op = 'list', $delta = 0, $edit = array()) {
  if (
$op == 'list') {
    return array(
     
0 => array(
       
'info' => 'Block cache per page with pager',
       
'cache' => BLOCK_NO_CACHE,
      ),
    );
  }
  elseif (
$op == 'view' && $delta == 0) {
    return
test_block_view();
  }
}
?>

The function that returns the content will use request_uri() and parse_url() to get the path that's requested and we will use that path as our own cache_id. We simply ignore all queries that might be available in the URI because we know that the block may have the same content for every page, despite any queries. This is a simple example, but you can add more logic depending on your use case of course. We store our entries in the cache_block table because that table is flushed enough so we don't have stale data on our pages.

<?php
/**
* Block callback.
*/
function test_block_view() {
 
$block = array();

 
// Get the URI without any query parameter.
 
$uri = parse_url(request_uri());
 
$cache_id = $uri['path'];

 
// Do we have something in cache ?
 
if ($cache = cache_get($cache_id, 'cache_block')) {
   
$block = $cache->data;
  }
 
// Otherwhise rebuild and cache it.
 
else {
   
$views_data = module_invoke('views', 'block', 'view', 'frontpage-block_1');
   
$block['subject'] = 'Frontpage';
   
$block['content'] = $views_data['content'];
   
cache_set($cache_id, $block, 'cache_block');
  }

  return
$block;
}
?>

Moving on and out

It's been a few weeks now since I sold my house where I've lived for 7 years, pretty amazing since I have this internal clock which forces me turn around stuff in my life every 3 years. Who knows if that changed too .. Anyway, I'll be homeless from the beginning of august if I don't start looking around for a new place to spent the next x years of my life - or at least sleep now and then. If you happen to know something around Gent, drop me a note, I'll be very interested to come and take a look if it's me-worthy.

Despite some rumours, I'm not moving out of the country - yet - New York will have to wait for a few years before I settle myself over there. And with the elections coming up, I might be moving to another country faster than expected .. :)

Hide the users icon in administration menu

I'm a huge fan of Administration menu, even more than projects like admin, toolbar or possibly others out there. If you want to delete some items from the menu, you need to implement hook_menu_link_alter() and reset the $item. Following snippets removes the users icon which shows the number of anonymous and authenticated users. Simple and powerfull.

<?php
/**
* Implementation of hook_menu_link_alter().
*/
function swentel_menu_link_alter(&$item, $menu) {
  if (
$item['title'] == 'icon_users') {
   
$item = NULL;
  }
}
?>

Drupalcon San Francisco and Display Suite


Due to Volcano activity on Iceland, I wasn't able to get to San Francisco for the biannual DrupalCon fest. But the Drupal community is that enthousiastic that we are setting up our own DrupalVolCon parties in Europe, already going on in London, Paris and in Antwerp. I'm supposed to give a session about Display Suite on wednesday, and that still might happen: we're busy testing and setting up streaming servers so we are able to stream our presentation on the internet at the time our sessions should take place in SF. All looks fine for now, so take that Eyjafjallajökull!

If you want to attend the session in Belgium, more info is available on http://belgium.drupalvolcon.com/

Update: we recorded the session and it's now available also on vimeo. Slides are at the bottom.

Display Suite profile

Related to our presentation, we just created a Display Suite profile containing all modules which are supported by Display Suite. We don't enable all modules by default in the installation profile, we just wanted to package them all, so you know what's possible.

We also packaged the Nodeform Columns module which enables you to organise your node forms in an easy way. If you don't really care about fieldgroups on the node form page, but need them on the front-end, you don't need to enable fieldgroups from CCK. The same applies to the tabs and cck fieldgroup tabs module, which are also included in the profile. Display Suite has this functionality by default.

You can see the full list of modules at http://drupal.org/node/775524, together with downloads of the profile and the packaged version of all modules with or without Drupal core included.

Important: some modules (like gmap and location) require the dev version to work properly, but for obvious reasons, the packed profile only contains official releases.

Anyway, sad I'm not there, but we're having fun here also!