Drupal 7: Automatically create menu paths by heirarchy, parents to children rule
In this blog post, we will go deeper into all the issues that come with implementing a proper URL paths hierarchy in Drupal 7 and try to propose working solutions where possible.
Why Implement Hierarchical Paths in the First Place?
If you have a website where editors can create pages and sub-pages, you will need to automatically output hierarchical paths if you are to implement a solid website. Let's take this collection of hierarchical, or tree-like, list of links:
A quick look at each link tells the user where the page is located in the structure of your website. For example, the second link directly tells us we're looking at the "mission" page which falls under the "about" page.
On top of that, when your website's links are properly organized into a hierarchy, you can use the Easy Breadcrumbs Drupal Module to, well, easily generate breadcrumbs, almost as simply as plugging the module and enabling it. Check this article on Wikipedia for more info about breadcrumbs, which might be more than necessary for websites with intricate navigational structures.
Requirements for Implementing Hierarchical Paths
First of all, you need the pathauto module. Second, you need a standard Drupal menu where your pages can be listed and organized into parent and child menu items. The menu is the one actually providing the hierarchy. Pathauto merely takes that tree-like hierarchy and tries, not very well as we'll see later, to generate a proper hierarchical path from it.
For pathauto to do its magic, you'll need to define a "pattern" for your page's paths. Let us spare you the research and assure you this is one of the best patterns we could find, and believe us, we've looked a lot. Of course, modify it according to your needs.
Basically, this pattern has the following special properties:
- If a node is not part of the menu tree, pathauto will then simply generate a path based on the title of the node. Super useful. This is something most other patterns fail at and your node ends up with no custom path at all if it's not in a menu.
- If the node is in the menu, and is on the top most level, this also defaults to its title. Exactly what we want.
- Finally, if the node is in a menu, and it has a parent, this pattern will correctly prepend the path of the parent menu item to the beginning of the path of the current item. Also, this will work recursively so menu items on deeper levels in the hierarchy will also get a proper path.
Unfortunately, this comes with certain limitations, which we believe would have been better addresses in the pathauto module itself. However, if you need to have this functionality properly implemented now, you need to write custom code as we detail below to handle edge cases.
In the future, we plan on creating a Drupal contrib module to address this issue as a whole or maybe even try, if possible, to push this functionality into the pathauto module.
Limitations and Solutions Where Possible
The first limitation is that a node with sub-menu items can be deleted by website editors, leaving all nodes below it in the menu with incorrect paths. Our solution here is simply to not allow editors to delete such nodes. We have previously detailed this approach in our conditionally preventing node deletion in Drupal tutorial.
The second limitation or bug is that menu items that are under the front page menu item will get a "front" slug added to the beginning or their URLs. This is definitely not desirable and we detail a fix for this issue in our blog post about removing the front slug from hierarchical paths generated by pathauto.
The third limitation is that when the path of the parent menu item changes, its child menu items don't get updated and hence their paths become incorrect. In our case, simply changing the title of the parent node will cause a change in its path and cause this limitation. We will present custom code that fixes this issue in the last section of this post.
Finally, there are more limitations that we couldn't address due to them being very specific cases or mostly not very essential if your website's permissions are properly configured. We might update this post in the future and tackle them, but for now, here's a listing of those extra issues.
- Paths generated by the views module aren't affected by our code. Luckily, only technical administrators add, edit, and delete views on our websites and they know how to handle path properly and manually.
- Rearranging the menu items from the Manage Menu admin interface is not handled by our code. We probably need to find the hooks used for the Manage Menu interface and implement our approach on those hooks. For now, we don't need this as our website editors don't have access to this admin interface.
- Similar to the previous point, if editors have access to the Mange Menu interface, they can create "recursive" or "infinite-looping" menus by creating menu items, without an actual page, that point to a parent page while including this menu item as a child of this parent. Very specific, but it might happen. Luckily, similar to the previous point, we don't need a solution for this case now.