How to handle urls for “mini sites” in panels 2
This post is about how to handle urls for portals or mini sites or groups where there are multiple subpages in a given area of the site.
I ran into a slightly puzzling problem this week while working with the Civicactions team in Mexico. We’re doing a project for a client who has a large site which is heavily focused on Organic Groups. We’re using panels 2 for the entire layout, and of course pathauto is also in use.
Here is the gist:
We have four node types which are og_node types. The types are:
- Campaigns
- Toolkits
- And a couple others…
So using path auto, if I have a campaign about water conservation, the path is:
campaigns/water_conserve -> node/123
node/% is overriden by panels, and using the panels arguments, we’ve got different layouts depending on if a campaign type node is passed in or a toolkit type node. (campaigns and toolkits have different sidebars, and some other stuff as well).
Okay, so that works fine, however each campaign has their own blog and the URL should be:
campaigns/water_conserve/blog
This should load another panel override where the URL is node/%/blog, but the above url DOES NOT map to node/123/blog, because the path module does not recourse back in the URL to find a match. With the blocks module (who would want to use this anymore?), this was okay using visibility settings, but it’s not too great to do in panels (even with mini panels as blocks).
So how do we resolve this?
I see three equally bad options:
- Write a hook into node_save and write a ton of url_alias entries like campaigns/water_conserve/blog, campaigns/water_conserve/resources, campaigns/water_conserve/people, etc. The problem with this is that it creates cruft, and it could leave artifacts, and it requires constant maintenance of these path aliases as new ones are added.
- We include logic everywhere (in all views, blocks, etc) to actually look at the URL and determine if it should load or not…. That’s pretty bad
- We build a RESTful structure using a slight hack in our custom client module This means that we find out that campaigns/water_conserve == “node/37″ and assume that campaigns/water_conserve/blog == “node/37/blog” (see below).
function mymod_menu($may_cache = false) {
if (!$may_cache) {
// $args
// for each arg
// remove the arg and see if the path that is left is in path auto
// example:
// campaigns/mycampaign/blog/superblog
// first loop:
// is campaigns/mycampaign/blog in the alias table (no).
// second loop:
// is campaigns/mycampaign in the alias table (yes) -> node/123
// set the path
$arguments = explode('/', $_GET['q']);
// Only limit this to a couple of url paths to keep it safe?
if (in_array($arguments[0],array('campaign','toolkit','group','organization'))) {
while ($removed_args[] = array_pop($arguments) ) {
$test = implode("/",$arguments);
if ($real_path = drupal_get_normal_path($test)) {
$real_path .= '/' . implode('/',$removed_args);
menu_set_active_item($real_path);
break;
}
}
}
}
I don’t love this either, but it seems to work just fine. Does anyone have a problem with this? Should it be an option in path? Does it even matter in D6?