planet

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;
}
?>

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;
  }
}
?>

Display Suite 1.1 'Fieldgroups baby'

After 2 months of hard work, we're proud to present you a new stable release of Display Suite and two new modules implementing the API, User displays and Views displays. A list of new features and bugfixes is available on the release notes of DS 6.x-1.1, make sure to read them as we had to introduce 2 small API changes. If you choose to upgrade, make sure you upgrade all other implementations too. A summary of cool new features:

  • Support for fieldgroups: the number one feature request by many users. You don't necessarily have to enable the fieldgroups module which comes with CCK, you can create as many as you like with the DS API via the interface. As a bonus, when the tabs module is enabled, you can change the output of your fieldgroups to tabs.
  • User Displays: first release which has support for the core profile module. Theming of the user profile finally got nice, especially in combination with fieldgroups support.
  • Views Displays: drag and drop your views, also with support for the Views attach module.
  • Region to block plugin: exposes regions per content type and build mode to a block.
  • Various other small new features like adding styles, simple panels support, location/gmap and syncing and copying display settings from one build mode to another.

New screencasts are available showing the new features and our demo site is also still available.

The roadmap has been updated, next focus is creating a full working version for Drupal 7. In the meantime, enjoy and see you hopefully at Drupalcon for our session about Display Suite!

New Display Suite toys: Views displays and ND Location

We've been quite busy with Display Suite since the first release. A lot of issues have been fixed and fieldgroups integration, the number one feature request by anyone out there, is almost done. We also created two new, rather small - but cool - modules which integrate perfectly with DS.

  • ND location: integrates with the location and Gmap modules. All location properties will be exposed as separate fields and you get an extra field which opens the marker info window on google maps, ideal for an overview page. We'll add a few other cool goodies to make this module rock even harder than it already does.
  • Views displays: all variables in the views.tpl.php are now 'fields' which you can put in the default set of regions. Extra fields/data are now very ease to add to your views displays.

You can see the power when combining these 2 modules in this short screencast. You can also click around on our demo site, still on the same URL, at http://demo.customsource.be/location.

Pages

Subscribe to RSS - planet

You are here