- About the author
- Jonathan Christopher
I have a love/hate relationship with WordPress Menus, I really do. If you’ve read Client Oriented WordPress Development you know why already, but for those that haven’t I’ll touch on the reasoning a bit. Our client websites aren’t your typical WordPress templates. We spend a lot of time structuring the way a site navigation should work and truth be told it’s not worth the time to make that a dynamic feature of the site as altering it would severely compromise the overall architecture of the project.
It’s not that we don’t trust clients, not at all, we just know how tempting it might be to alter the focal point of your website to better reflect the new widget that got released this week. It might seem awesome for everyone making the decision to do that, but the people actually viewing your site are going to be put at odds with the alteration. Perspective means a lot when it comes to designing a site navigation and comparing internal company views to those of the visitors you’d like to become customers is a big deal.
Circling back to WordPress Menus here I find myself at odds with their original purpose. If we go back in time a bit we remember that WordPress menus originated with WooThemes, a company who builds commercial WordPress themes for the purpose of massive customization so as to provide a turnkey solution for the maximum number of their customers. Clients are a different story altogether in my opinion, and navigation customization doesn’t fit the mold of what we’re trying to do as a service to them. That said, it’s really rare for me to use WordPress Menus in client sites, but there are always edge cases.
Two client projects as of late are atypically (for me) making use of WordPress Menus in a pretty big way. In the most direct example I’m using two main Menu sections to power a couple of navigation areas on the website. The first use case is pretty standard and will act as the global navigation of the site. The nav though is pretty complex and actually will undergo consistent periodic updates, which leads me to the second area in which I’ll be heavily utilizing WordPress Menus.
One client is heavily involved in the sale of goods on their site. Tightly aligned with that is a major focus from the marketing team to ensure the site navigation is always up-to-date with their latest efforts in the overall marketing campaign. Tied with that is the need to always make sure the site navigation aligns with their product catalog which necessitates constant updating to the nav.
Between these two use cases, both of which heavily rely on navigation customization outside the normal use case of statically marking up a site nav and using other elements (e.g. sidebars) to provide contextual links based on the choice of navigation in a global list of links, an additional degree of control is completely necessary here.
As you can see, the plugin doesn’t do much quite yet, but hopefully based on community needs, the feature set will expand and become more universally useful.
As I was discussing the site with the client and outlining exactly what would be needed over time, their unique set of needs lead me to conclude not only that Menus are the right solution, but it’d actually make sense to implement some sort of Menu duplication functionality to make their lives easier. Traditionally the usage of Menus surrounds an updating of the links in place and those links being pushed live instantly. In my case, however, marketing efforts would require the updating of entire Menus at a clip based on the current active campaign. That would often result in the need of implementing a Menu that might be live only for a week or two, and then the need to revert back to the original.
Sure, it’s possible to add the links to the original Menu and then take them out again once the campaign has run it’s course, but that seemed like too much work in my opinion, and left a lot open for human error to be honest. Menu management can be extremely tedious, so I thought it’d be great to make a carbon copy of a Menu for the current campaign with a workflow that went something like this:
The requirement to research Menu duplication stemmed from the fact that the Meny could be ~40 nested items to begin with. To make a copy by hand would take way too long than anyone has time for, so duplication seemed appropriate here. Again, writing out this workflow makes it sound like making the edits to a single menu and then reverting them at the appropriate time would be more straightforward, but another small use case is coming up with potentially recyclable Menus that can get switched with one click instead of constant editing on the part of the client. It’s all about time-saving here.
Since I don’t use Menus too much, this was a great excuse to dissect them a bit more than usual. I was at first but shouldn’t be surprised to learn that Menus are a clever use of WordPress Taxonomies under the hood more or less. That made working with them a bit interesting to get up and running with, but after some research of the WordPress code base, it worked out quite well.
Building this plugin essentially came down to some trial and error on my part as the Menus architecture isn’t fully documented and I needed to check out some functions I’d never used before. That said, the plugin is definitely at version 0.1 and merely supports what I needed to build into my client projects at this time. Some short discussions on Twitter lead me to uncover some additional use cases (outlined in the Roadmap below) that I hope to get some help on.
The five hundred foot view is as follows: Duplicate Menu takes a source Menu and asks only one thing of you to duplicate it: a new name. After entering a new name, the plugin will first create a new empty Menu and then pull the source menu items via
wp_get_nav_menu_items. From there it will iterate through each source Menu item, and recreate it as a new record in our new Menu via
wp_update_nav_menu_item (needs documentation). Appropriate data is used from the source menu item, and updated for our new record to ensure we’ve copied the source instead of hijacking it, which would cause issue with both Menus when updates were made to either.
Perhaps the most difficult issue to overcome when building out the duplication was to keep track of nesting. If you check out the plugin source you’ll note that a second pass needed to be taken should any source menu item have a parent associated with it. As the source items are iterated, the keys are mapped to the keys of the new menu to allow for the relationship to the new parent to be made, else we would be setting the Menu item parent for the cloned menu to the parent
id of a source Menu item. It’s a bit confusing at first, and tripped me up my first time through as well. Once all Menu items have been cloned and given proper parents, the duplication is complete. It’s a simple process for the most part, but admittedly needs some more rigorous testing.
Here’s the deal: I’d love some help with this plugin. As with many of my plugins, the public facing repo is hosted on GitHub and I’d absolutely love to get some pull requests because this plugin begs to solve those edge case problems many people have.
Out of the gate I need to do some testing. WordPress is awesome in handling any errors that might creep up during the duplication process, but I need to implement better feedback should something go wrong. I also need to test more elaborate Menus to make sure duplication results in an expected outcome. The more people able to test the better!
One of the biggest requests I got during short talks on Twitter was the ability to duplicate a Menu from one site to another in a Multisite install. I like that idea and hope to research it down the line, but hope people who have that need have some direct experience with their use cases and are able to help out with a pull request or two.
There are likely many other features that could be added to the plugin, but I’d love to write it in such a way that it provides a base from which to build upon. Menu duplication is really an extreme edge case, so it’s likely that feature requests would be single use and better suited for an
filter. Coming up with an effective way to implement that in the plugin would be awesome as well. Feedback is more than welcome, please enjoy the plugin if it suits you!