Pathauto is one of those modules that everyone blindly installs on each of his sites. It allows you to automatically create pretty urls for all your content based on some properties of that content. Pathauto uses the Token module to allow the user to define url patterns (using the admin interface) based on tokens.
On sites with a hierarchical menu a very popular pattern (token) used is the "menupath", which is basically results into a "url-ified" version of your breadcrumb. The menupath can become very long though in case you have a deep menu structure or have a few menu items that have very long titles. Since Pathauto cuts of the long paths after a certain length (configurable via "Maximum alias length"), a lot of urls (for items deep in the menu tree) might become very similar.
One of the most important reasons for having pretty urls is search engine optimisation (SEO). But in long urls the most relevant keywords for your page are at the end of your url.
A good compromise in this case is to use only the first two (or three) menu items at the beginning of your trail and the title of the page itself. Let's see how we can build a token that we can use for our Pathauto patterns that does this. We'll call it "short menupath".
To define a new token, you must do two things: you implement hook_token_list and hook_token_values.
The first one tells the Token module what your token is named and gives a description of what it does.
The second one, hook_token_values gives the value to Token module for each available token for a certain object. So it learns token how to replace a certain token for a certain object. For example if you have a page node titled This is a page node it would replace all occurrences of the [title] token with This is a page node.
We can conclude by implementing these hooks now for our "short menupath" token.
/**
* Implementation of hook_token_list().
*/
function my_module_token_list($type = 'all') {
if ($type == 'node' || $type == 'all') {
$tokens['node']['short-menupath'] = t("The menu path (as reflected in the breadcrumb), not including Home or [menu]. Separated by /. If length is greater then 3 items, only the first two and last are used.");
$tokens['node']['short-menupath-raw'] = t("The unfiltered menu path (as reflected in the breadcrumb), not including Home or [menu]. Separated by /. If length is greater then 3 items, only the first two and last are used. WARNING - raw user input.");
return $tokens;
}
}
/**
* Implementation of hook_token_values().
*/
function my_module_token_values($type, $object = NULL, $options = array()) {
$path = drupal_get_path('module', 'token');
require_once("$path/token_node.inc");
$values = array();
switch ($type) {
case 'node':
$node = $object;
// Try to get the menu data.
$mlid = db_result(db_query("SELECT mlid FROM {menu_links} WHERE link_path = '%s'", 'node/'. $node->nid));
// Now get the menu related information.
if (!empty($mlid) || !empty($node->menu['mlid']) || !empty($node->menu['plid'])) {
$menu_link = menu_link_load($mlid);
$menus = menu_get_menus();
$menu = isset($menus[$menu_link['menu_name']]) ? $menus[$menu_link['menu_name']] : '';
$trail_raw = _menu_titles($menu_link, $node->nid);
$trail = array();
foreach ($trail_raw as $title) {
$trail[] = check_plain($title);
}
$short_trail_raw = array();
if (count($trail_raw) > 3) {
$short_trail_raw[0] = $trail_raw[0];
$short_trail_raw[1] = $trail_raw[1];
$short_trail_raw[2] = $trail_raw[count($trail_raw) - 1];
}
else {
$short_trail_raw = $trail;
}
$short_trail = array();
foreach ($short_trail_raw as $title) {
$short_trail[] = check_plain($title);
}
$values['short-menupath'] = implode('/', $short_trail);
$values['short-menupath-raw'] = implode('/', $short_trail_raw);
}
else {
$values['short-menupath'] = '';
$values['short-menupath-raw'] = '';
}
break;
}
return $values;
}
Comments
Coding style is not important for this edutorial article. I've just taken the bits and bolts from the menupath token implementation and added a few extras.
But thanks for noting!
Take a look at array_splice():
$a = array(0,1,2,3,4,5,6,7,8);
array_splice($a, 2, -1, array());
And there's no need to create $trail out of trail_raw since you don't use it. Well you did, but it was a mistake because you used it to create $short_trail_raw.
Post new comment