Using Saved Custom Widget Options

In this three part series, we’re looking at how to add a custom option to the WordPress Custom Menu widget that will allow us to display menu item descriptions. This is the final post in this series. In this tutorial, we’ll cover how to use the custom option we created in the first tutorial. Here are the three posts in this series:

Getting Started

Please note: This post is based on the code from the first two posts in this series. If you haven’t already added the code from those tutorials to your theme, the code in this tutorial will not work properly.

In the first post in this series, we created a custom option in the WordPress Custom Menu widget. In this post we’re going to use that option to determine whether or not to display menu item descriptions on a per-menu basis.

In the second post in this series, we created the code that actually displays the menu descriptions, so we’re most of the way there. However, in order to style menus with descriptions enabled differently than the standard menus we’ll want to give our descriptive menus an additional class name. To do that, we’ll first create a function that adds class names to an array.

function prefix_add_description_class( $nav_menu_args, $nav_menu, $args ) {
	$nav_menu_args['menu_class'] = 'menu prefix-descriptive-menu';

	return $nav_menu_args;
}

This function will be (conditionally) attached to the widget_nav_menu_args filter hook. This hook passes three parameters to our function.

$nav_menu_args array An array of arguments passed to wp_nav_menu() to retrieve a custom menu.
$nav_menu stdClass Nav menu object for the current menu.
$args array Display arguments for the current widget.

The only parameter we’re dealing with is the $nav_menu_args array. You’ll notice we added “menu prefix-descriptive-menu” to the “menu_class” array item. The “prefix-descriptive-menu” class is the class name that is specific to our descriptive menus. However, we must also add the “menu” class as well. WordPress typically generates the “menu” class on its own, but if there is already a class name specified, it doesn’t add the “menu” class. Since we’re trying to add a class, not replace the default “menu” class, we’ll want to include the “menu” class in our string of classes.

Next we need to clean up some code we added in the last tutorial. Since we’re only going to enable description support for menu widgets that have that feature enabled, we’ll want to remove this line that we added in the previous post:

add_filter( 'walker_nav_menu_start_el', 'prefix_nav_description', 10, 4 );

This line added description support to every menu, so we need to get rid of it before moving on. You’ll see it show up again later in this post, but it won’t be used on every menu any more.

Using the Saved Options

To finally put everything together and use the options we saved in the first post, we’ll use the following code:

function prefix_menu_description_control( $params ) {

	// Gets every custom menu widget from the database.
	$widget_settings = get_option('widget_nav_menu');

	// Does the current menu widget have descriptions turned on?
	if ( !empty( $widget_settings[$params[1]['number']]['description'] ) ) {

		// Adds filter to display menu item descriptions.
		add_filter( 'walker_nav_menu_start_el', 'prefix_nav_description', 10, 4 );
		add_filter( 'widget_nav_menu_args', 'prefix_add_description_class', 10, 3 );
	} else {

		// Removes filter to display menu item descriptions.
		remove_filter( 'walker_nav_menu_start_el', 'prefix_nav_description', 10, 4 );
		remove_filter( 'widget_nav_menu_args', 'prefix_add_description_class', 10, 3 );
	}

	// Return the unmodified $params.
	return $params;
}
add_filter( 'dynamic_sidebar_params', 'prefix_menu_description_control' );

We’re attaching this function to the dynamic_sidebar_params filter which passes us the array of parameters that are being passed to each widget’s callback function. We’ll be using this array to determine which instance of the custom menu widget is being displayed at any given time.

First we get the settings for all the Custom Menu widgets that exist in the database. Next we use an if statement to check if the current widget has the description checkbox checked. If it does, we add the functions we created previously to their respective filters. However, if the box was unchecked, we remove the functions from those filters.

The reason we have to remove functions from the filters is because once a function is added to a filter, it runs every time the filter is called. Since the filter is called for each Custom Menu widget, we could potentially add description support to the first menu widget and accidentally add description support to any additional Custom Menu widgets on the page. Removing the filters when the checkbox is unchecked ensures that we don’t have to worry about that issue.

Finally, we return the unmodified $params variable. We only used this variable to figure out what instance of the Custom Menu widget we were working with each time we ran our prefix_menu_description_control() function.

This has been a little more technical than the first couple tutorials in this series. If you’re having any trouble with it, feel free to use the contact page to get a hold of me (or check out the Longview theme that has menu description support built in).