July 15th, 2008

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:

  1. 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.
  2. 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
  3. 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?

July 3rd, 2008

Helpers_user: The user API that never was

I was writing an install profile for a out-of-the-box workflow install profile to be used by media organizations today, when I ran into the rote task of adding roles and permissions.

(for reference, see my last article on workflow configuration in drupal)

So being the programmer who will write something in a day which takes an hour to run to save 5 minutes, I decided to scratch a long standing itch:

The Drupal User System API.

I love the simplicity of the drupal user system, but like many things in drupal, it wants you to use forms to admin it, and the DB model is inherently tied to the controller (not good).

So I decided to contribute this to the helpers module. It provides some simple functions like:

helpers_user_help($section)
permissions_get(unknown_type $rid)
permissions_set(unknown_type $rid, unknown_type $perms = array)
role_add(string $name)
role_get(int $rid = 0, string $name = “”)
user_add_roles($uid, $roles = array)
user_delete_roles($uid, $roles = array)

Simple stuff, but AFAIK, lacking in drupal.

In addition, I also wrote a full set of simplete tests for it which can be found in the tests directory.

The patch can be found at:
http://drupal.org/node/252058
Hope others find this helpful!

-Jacob

July 1st, 2008

Solving bad IA using enterprise search (Reverse Advanced Search)

Since I started working with Apache Solr in Drupal, I’ve realized how much client money has been wasted making ill advised advanced searches. We’ve all gotten the requests for “advanced” searches and it makes any IA-god fearing developer cringe. For the 1% of users who use them, you blow tons of budget, and the result is often quite poor because the client doesn’t really know their data or their users that well.

For those of you who are unfamiliar with faceted search compare the following:

I did a search for WSXGA because I’m looking for a laptop with decent resolution on two sites.

Laptops Direct

vs.

New Egg

(click to enlarge image in new window)

The New Egg search lets me filter, so I know that I’m looking for a laptop between $750 -> $1000, I’ll get 5 results. After that filter, I’ll know what’s available, and the # per manufacturer etc.

Contrast that with an advanced search form where I have to put in all my criteria, and hope I get a result. I might also miss certain results if my vocabulary is bad, or I don’t understand that the website says “high resolution” instead of WSXGA, so I don’t select it.

I think it’s obvious to anyone why faceted search is a good thing. In my next post, I’ll be exploring why is hasn’t gotten widespread adoption, particularly in the small business / NGO sector, and how I plan to help change that.

How To find me

Telephone: +1 510.277.0891 | Email: jacobsingh at gmail daht calm

Solution Graphics