[wp-hackers] wp_nav_menu too simplistic?

John Bloch jbloch at olympianetworks.com
Tue Apr 6 20:13:55 UTC 2010


This custom walker class will give you a filter to directly modify the
url of individual menu items. Put this into your theme's function file
and, when you call the menu, add "walker=Custom_Walker_Nav_Menu" to
the function's arguments.

class Custom_Walker_Nav_Menu extends Walker {
	/**
	 * @see Walker::$tree_type
	 * @since 3.0.0
	 * @var string
	 */
	var $tree_type = array( 'post_type', 'taxonomy', 'custom' );

	/**
	 * @see Walker::$db_fields
	 * @since 3.0.0
	 * @todo Decouple this.
	 * @var array
	 */
	var $db_fields = array( 'parent' => 'post_parent', 'id' => 'object_id' );

	/**
	 * @see Walker::start_lvl()
	 * @since 3.0.0
	 *
	 * @param string $output Passed by reference. Used to append
additional content.
	 * @param int $depth Depth of page. Used for padding.
	 */
	function start_lvl(&$output, $depth) {
		$indent = str_repeat("\t", $depth);
		$output .= "\n$indent<ul class=\"sub-menu\">\n";
	}

	/**
	 * @see Walker::end_lvl()
	 * @since 3.0.0
	 *
	 * @param string $output Passed by reference. Used to append
additional content.
	 * @param int $depth Depth of page. Used for padding.
	 */
	function end_lvl(&$output, $depth) {
		$indent = str_repeat("\t", $depth);
		$output .= "$indent</ul>\n";
	}

	/**
	 * @see Walker::start_el()
	 * @since 3.0.0
	 *
	 * @param string $output Passed by reference. Used to append
additional content.
	 * @param object $item Menu item data object.
	 * @param int $depth Depth of menu item. Used for padding.
	 * @param int $current_page Menu item ID.
	 * @param array $args
	 */
	function start_el(&$output, $item, $depth, $args) {
		$indent = ( $depth ) ? str_repeat( "\t", $depth ) : '';

		$classes = $value = '';
		if ( 'frontend' == $args->context ) {
			global $wp_query;

			$classes = array( 'menu-item', 'menu-item-type-'. $item->type,
$item->classes );

			if ( 'custom' != $item->object )
				$classes[] = 'menu-item-object-'. $item->object;

			if ( $item->object_id == $wp_query->get_queried_object_id() )
				$classes[] = 'current-menu-item';

			// @todo add classes for parent/child relationships

			$classes = join( ' ', apply_filters( 'nav_menu_css_class',
array_filter( $classes ), $item ) );
			$classes = ' class="' . esc_attr( $classes ) . '"';
		} else {
			$value = ' value="' . $item->ID . '"';
		}


$item->url = apply_filters( 'my_custom_nav_menu_links_filter',
(string)$item->url );

		$output .= $indent . '<li id="menu-item-'. $item->ID . '"' . $value
. $classes .'>' . wp_get_nav_menu_item( $item, $args->context, $args
);
	}

	/**
	 * @see Walker::end_el()
	 * @since 3.0.0
	 *
	 * @param string $output Passed by reference. Used to append
additional content.
	 * @param object $item Page data object. Not used.
	 * @param int $depth Depth of page. Not Used.
	 */
	function end_el(&$output, $item, $depth) {
		$output .= "</li>\n";
	}

}


John P. Bloch


On Tue, Apr 6, 2010 at 3:58 PM, John Bloch <jbloch at olympianetworks.com>wrote:

> Or you could declare your own Walker class, copying the exact nav menu
> walker and just adding your own filters onto whatever you want, then just
> use the new class name as the 'walker' attribute when you call the menu.
>
> Also, there are filters and actions all over the menus. For example,
> nav_menu_css_class is a hook that lets you sort through an array of classes
> applied to each and every menu item and add or remove classes. That's just
> one of at least a dozen that I saw while taking a cursory look through the
> menu functions.
>
> John P. Bloch
>
>
> On Tue, Apr 6, 2010 at 3:27 PM, Otto <otto at ottodestruct.com> wrote:
>
>> On Tue, Apr 6, 2010 at 2:16 PM, John Bloch <jbloch at olympianetworks.com>
>> wrote:
>> > Even without that pre-built functionality, there are still the normal
>> hooks
>> > that you have when updating a page. Nobody said it's easy to code such a
>> > plugin; I just said that it was possible.
>>
>> Yuck. Okay, so I consider hacky ways of doing things to be invalid.
>> Therefore, it is not possible. :)
>>
>> There's no action hooks or filters or anything in the menu generation
>> system. Basically, the wp_setup_nav_menu_item builds the url and such,
>> then that gets passed to wp_get_nav_menu_item which builds the link,
>> and then it gets shoved into the output.
>>
>> Short of hideous regexp and filtering that whole menu and such,
>> there's no way to insert stuff into the menu dynamically. All you can
>> do is recognize changes and then modify the menu (and probably break
>> it in the process, the ordering system is fragile as well).
>>
>> A better solution would be to make the menu system not all so focused
>> on static links and use something more like widgets, which get called
>> to build their link (and which could then be static, if desired). Then
>> it'd be more configurable and more expandable.  Plus we wouldn't need
>> all this Woo code for Ajax and such, since a widget system already
>> exists and is in the core.
>>
>> -Otto
>> _______________________________________________
>> wp-hackers mailing list
>> wp-hackers at lists.automattic.com
>> http://lists.automattic.com/mailman/listinfo/wp-hackers
>>
>
>


More information about the wp-hackers mailing list