wp/wp-includes/nav-menu-template.php
changeset 9 177826044cd9
parent 7 cf61fcea0001
child 16 a86126ab1dd4
equal deleted inserted replaced
8:c7c34916027a 9:177826044cd9
    46  * @return string|false|void Menu output if $echo is false, false if there are no items or no menu was found.
    46  * @return string|false|void Menu output if $echo is false, false if there are no items or no menu was found.
    47  */
    47  */
    48 function wp_nav_menu( $args = array() ) {
    48 function wp_nav_menu( $args = array() ) {
    49 	static $menu_id_slugs = array();
    49 	static $menu_id_slugs = array();
    50 
    50 
    51 	$defaults = array( 'menu' => '', 'container' => 'div', 'container_class' => '', 'container_id' => '', 'menu_class' => 'menu', 'menu_id' => '',
    51 	$defaults = array(
    52 	'echo' => true, 'fallback_cb' => 'wp_page_menu', 'before' => '', 'after' => '', 'link_before' => '', 'link_after' => '', 'items_wrap' => '<ul id="%1$s" class="%2$s">%3$s</ul>', 'item_spacing' => 'preserve',
    52 		'menu'            => '',
    53 	'depth' => 0, 'walker' => '', 'theme_location' => '' );
    53 		'container'       => 'div',
       
    54 		'container_class' => '',
       
    55 		'container_id'    => '',
       
    56 		'menu_class'      => 'menu',
       
    57 		'menu_id'         => '',
       
    58 		'echo'            => true,
       
    59 		'fallback_cb'     => 'wp_page_menu',
       
    60 		'before'          => '',
       
    61 		'after'           => '',
       
    62 		'link_before'     => '',
       
    63 		'link_after'      => '',
       
    64 		'items_wrap'      => '<ul id="%1$s" class="%2$s">%3$s</ul>',
       
    65 		'item_spacing'    => 'preserve',
       
    66 		'depth'           => 0,
       
    67 		'walker'          => '',
       
    68 		'theme_location'  => '',
       
    69 	);
    54 
    70 
    55 	$args = wp_parse_args( $args, $defaults );
    71 	$args = wp_parse_args( $args, $defaults );
    56 
    72 
    57 	if ( ! in_array( $args['item_spacing'], array( 'preserve', 'discard' ), true ) ) {
    73 	if ( ! in_array( $args['item_spacing'], array( 'preserve', 'discard' ), true ) ) {
    58 		// invalid value, fall back to default.
    74 		// invalid value, fall back to default.
    98 
   114 
    99 	// Get the nav menu based on the requested menu
   115 	// Get the nav menu based on the requested menu
   100 	$menu = wp_get_nav_menu_object( $args->menu );
   116 	$menu = wp_get_nav_menu_object( $args->menu );
   101 
   117 
   102 	// Get the nav menu based on the theme_location
   118 	// Get the nav menu based on the theme_location
   103 	if ( ! $menu && $args->theme_location && ( $locations = get_nav_menu_locations() ) && isset( $locations[ $args->theme_location ] ) )
   119 	if ( ! $menu && $args->theme_location && ( $locations = get_nav_menu_locations() ) && isset( $locations[ $args->theme_location ] ) ) {
   104 		$menu = wp_get_nav_menu_object( $locations[ $args->theme_location ] );
   120 		$menu = wp_get_nav_menu_object( $locations[ $args->theme_location ] );
       
   121 	}
   105 
   122 
   106 	// get the first menu that has items if we still can't find a menu
   123 	// get the first menu that has items if we still can't find a menu
   107 	if ( ! $menu && !$args->theme_location ) {
   124 	if ( ! $menu && ! $args->theme_location ) {
   108 		$menus = wp_get_nav_menus();
   125 		$menus = wp_get_nav_menus();
   109 		foreach ( $menus as $menu_maybe ) {
   126 		foreach ( $menus as $menu_maybe ) {
   110 			if ( $menu_items = wp_get_nav_menu_items( $menu_maybe->term_id, array( 'update_post_term_cache' => false ) ) ) {
   127 			if ( $menu_items = wp_get_nav_menu_items( $menu_maybe->term_id, array( 'update_post_term_cache' => false ) ) ) {
   111 				$menu = $menu_maybe;
   128 				$menu = $menu_maybe;
   112 				break;
   129 				break;
   117 	if ( empty( $args->menu ) ) {
   134 	if ( empty( $args->menu ) ) {
   118 		$args->menu = $menu;
   135 		$args->menu = $menu;
   119 	}
   136 	}
   120 
   137 
   121 	// If the menu exists, get its items.
   138 	// If the menu exists, get its items.
   122 	if ( $menu && ! is_wp_error($menu) && !isset($menu_items) )
   139 	if ( $menu && ! is_wp_error( $menu ) && ! isset( $menu_items ) ) {
   123 		$menu_items = wp_get_nav_menu_items( $menu->term_id, array( 'update_post_term_cache' => false ) );
   140 		$menu_items = wp_get_nav_menu_items( $menu->term_id, array( 'update_post_term_cache' => false ) );
       
   141 	}
   124 
   142 
   125 	/*
   143 	/*
   126 	 * If no menu was found:
   144 	 * If no menu was found:
   127 	 *  - Fall back (if one was specified), or bail.
   145 	 *  - Fall back (if one was specified), or bail.
   128 	 *
   146 	 *
   129 	 * If no menu items were found:
   147 	 * If no menu items were found:
   130 	 *  - Fall back, but only if no theme location was specified.
   148 	 *  - Fall back, but only if no theme location was specified.
   131 	 *  - Otherwise, bail.
   149 	 *  - Otherwise, bail.
   132 	 */
   150 	 */
   133 	if ( ( !$menu || is_wp_error($menu) || ( isset($menu_items) && empty($menu_items) && !$args->theme_location ) )
   151 	if ( ( ! $menu || is_wp_error( $menu ) || ( isset( $menu_items ) && empty( $menu_items ) && ! $args->theme_location ) )
   134 		&& isset( $args->fallback_cb ) && $args->fallback_cb && is_callable( $args->fallback_cb ) )
   152 		&& isset( $args->fallback_cb ) && $args->fallback_cb && is_callable( $args->fallback_cb ) ) {
   135 			return call_user_func( $args->fallback_cb, (array) $args );
   153 			return call_user_func( $args->fallback_cb, (array) $args );
   136 
   154 	}
   137 	if ( ! $menu || is_wp_error( $menu ) )
   155 
       
   156 	if ( ! $menu || is_wp_error( $menu ) ) {
   138 		return false;
   157 		return false;
       
   158 	}
   139 
   159 
   140 	$nav_menu = $items = '';
   160 	$nav_menu = $items = '';
   141 
   161 
   142 	$show_container = false;
   162 	$show_container = false;
   143 	if ( $args->container ) {
   163 	if ( $args->container ) {
   150 		 *                    Default is array containing 'div' and 'nav'.
   170 		 *                    Default is array containing 'div' and 'nav'.
   151 		 */
   171 		 */
   152 		$allowed_tags = apply_filters( 'wp_nav_menu_container_allowedtags', array( 'div', 'nav' ) );
   172 		$allowed_tags = apply_filters( 'wp_nav_menu_container_allowedtags', array( 'div', 'nav' ) );
   153 		if ( is_string( $args->container ) && in_array( $args->container, $allowed_tags ) ) {
   173 		if ( is_string( $args->container ) && in_array( $args->container, $allowed_tags ) ) {
   154 			$show_container = true;
   174 			$show_container = true;
   155 			$class = $args->container_class ? ' class="' . esc_attr( $args->container_class ) . '"' : ' class="menu-'. $menu->slug .'-container"';
   175 			$class          = $args->container_class ? ' class="' . esc_attr( $args->container_class ) . '"' : ' class="menu-' . $menu->slug . '-container"';
   156 			$id = $args->container_id ? ' id="' . esc_attr( $args->container_id ) . '"' : '';
   176 			$id             = $args->container_id ? ' id="' . esc_attr( $args->container_id ) . '"' : '';
   157 			$nav_menu .= '<'. $args->container . $id . $class . '>';
   177 			$nav_menu      .= '<' . $args->container . $id . $class . '>';
   158 		}
   178 		}
   159 	}
   179 	}
   160 
   180 
   161 	// Set up the $menu_item variables
   181 	// Set up the $menu_item variables
   162 	_wp_menu_item_classes_by_context( $menu_items );
   182 	_wp_menu_item_classes_by_context( $menu_items );
   163 
   183 
   164 	$sorted_menu_items = $menu_items_with_children = array();
   184 	$sorted_menu_items = $menu_items_with_children = array();
   165 	foreach ( (array) $menu_items as $menu_item ) {
   185 	foreach ( (array) $menu_items as $menu_item ) {
   166 		$sorted_menu_items[ $menu_item->menu_order ] = $menu_item;
   186 		$sorted_menu_items[ $menu_item->menu_order ] = $menu_item;
   167 		if ( $menu_item->menu_item_parent )
   187 		if ( $menu_item->menu_item_parent ) {
   168 			$menu_items_with_children[ $menu_item->menu_item_parent ] = true;
   188 			$menu_items_with_children[ $menu_item->menu_item_parent ] = true;
       
   189 		}
   169 	}
   190 	}
   170 
   191 
   171 	// Add the menu-item-has-children class where applicable
   192 	// Add the menu-item-has-children class where applicable
   172 	if ( $menu_items_with_children ) {
   193 	if ( $menu_items_with_children ) {
   173 		foreach ( $sorted_menu_items as &$menu_item ) {
   194 		foreach ( $sorted_menu_items as &$menu_item ) {
   174 			if ( isset( $menu_items_with_children[ $menu_item->ID ] ) )
   195 			if ( isset( $menu_items_with_children[ $menu_item->ID ] ) ) {
   175 				$menu_item->classes[] = 'menu-item-has-children';
   196 				$menu_item->classes[] = 'menu-item-has-children';
       
   197 			}
   176 		}
   198 		}
   177 	}
   199 	}
   178 
   200 
   179 	unset( $menu_items, $menu_item );
   201 	unset( $menu_items, $menu_item );
   180 
   202 
   187 	 * @param stdClass $args              An object containing wp_nav_menu() arguments.
   209 	 * @param stdClass $args              An object containing wp_nav_menu() arguments.
   188 	 */
   210 	 */
   189 	$sorted_menu_items = apply_filters( 'wp_nav_menu_objects', $sorted_menu_items, $args );
   211 	$sorted_menu_items = apply_filters( 'wp_nav_menu_objects', $sorted_menu_items, $args );
   190 
   212 
   191 	$items .= walk_nav_menu_tree( $sorted_menu_items, $args->depth, $args );
   213 	$items .= walk_nav_menu_tree( $sorted_menu_items, $args->depth, $args );
   192 	unset($sorted_menu_items);
   214 	unset( $sorted_menu_items );
   193 
   215 
   194 	// Attributes
   216 	// Attributes
   195 	if ( ! empty( $args->menu_id ) ) {
   217 	if ( ! empty( $args->menu_id ) ) {
   196 		$wrap_id = $args->menu_id;
   218 		$wrap_id = $args->menu_id;
   197 	} else {
   219 	} else {
   198 		$wrap_id = 'menu-' . $menu->slug;
   220 		$wrap_id = 'menu-' . $menu->slug;
   199 		while ( in_array( $wrap_id, $menu_id_slugs ) ) {
   221 		while ( in_array( $wrap_id, $menu_id_slugs ) ) {
   200 			if ( preg_match( '#-(\d+)$#', $wrap_id, $matches ) )
   222 			if ( preg_match( '#-(\d+)$#', $wrap_id, $matches ) ) {
   201 				$wrap_id = preg_replace('#-(\d+)$#', '-' . ++$matches[1], $wrap_id );
   223 				$wrap_id = preg_replace( '#-(\d+)$#', '-' . ++$matches[1], $wrap_id );
   202 			else
   224 			} else {
   203 				$wrap_id = $wrap_id . '-1';
   225 				$wrap_id = $wrap_id . '-1';
       
   226 			}
   204 		}
   227 		}
   205 	}
   228 	}
   206 	$menu_id_slugs[] = $wrap_id;
   229 	$menu_id_slugs[] = $wrap_id;
   207 
   230 
   208 	$wrap_class = $args->menu_class ? $args->menu_class : '';
   231 	$wrap_class = $args->menu_class ? $args->menu_class : '';
   229 	 * @param stdClass $args  An object containing wp_nav_menu() arguments.
   252 	 * @param stdClass $args  An object containing wp_nav_menu() arguments.
   230 	 */
   253 	 */
   231 	$items = apply_filters( "wp_nav_menu_{$menu->slug}_items", $items, $args );
   254 	$items = apply_filters( "wp_nav_menu_{$menu->slug}_items", $items, $args );
   232 
   255 
   233 	// Don't print any markup if there are no items at this point.
   256 	// Don't print any markup if there are no items at this point.
   234 	if ( empty( $items ) )
   257 	if ( empty( $items ) ) {
   235 		return false;
   258 		return false;
       
   259 	}
   236 
   260 
   237 	$nav_menu .= sprintf( $args->items_wrap, esc_attr( $wrap_id ), esc_attr( $wrap_class ), $items );
   261 	$nav_menu .= sprintf( $args->items_wrap, esc_attr( $wrap_id ), esc_attr( $wrap_class ), $items );
   238 	unset( $items );
   262 	unset( $items );
   239 
   263 
   240 	if ( $show_container )
   264 	if ( $show_container ) {
   241 		$nav_menu .= '</' . $args->container . '>';
   265 		$nav_menu .= '</' . $args->container . '>';
       
   266 	}
   242 
   267 
   243 	/**
   268 	/**
   244 	 * Filters the HTML content for navigation menus.
   269 	 * Filters the HTML content for navigation menus.
   245 	 *
   270 	 *
   246 	 * @since 3.0.0
   271 	 * @since 3.0.0
   250 	 * @param string   $nav_menu The HTML content for the navigation menu.
   275 	 * @param string   $nav_menu The HTML content for the navigation menu.
   251 	 * @param stdClass $args     An object containing wp_nav_menu() arguments.
   276 	 * @param stdClass $args     An object containing wp_nav_menu() arguments.
   252 	 */
   277 	 */
   253 	$nav_menu = apply_filters( 'wp_nav_menu', $nav_menu, $args );
   278 	$nav_menu = apply_filters( 'wp_nav_menu', $nav_menu, $args );
   254 
   279 
   255 	if ( $args->echo )
   280 	if ( $args->echo ) {
   256 		echo $nav_menu;
   281 		echo $nav_menu;
   257 	else
   282 	} else {
   258 		return $nav_menu;
   283 		return $nav_menu;
       
   284 	}
   259 }
   285 }
   260 
   286 
   261 /**
   287 /**
   262  * Add the class property classes for the current context, if applicable.
   288  * Add the class property classes for the current context, if applicable.
   263  *
   289  *
   270  * @param array $menu_items The current menu item objects to which to add the class property information.
   296  * @param array $menu_items The current menu item objects to which to add the class property information.
   271  */
   297  */
   272 function _wp_menu_item_classes_by_context( &$menu_items ) {
   298 function _wp_menu_item_classes_by_context( &$menu_items ) {
   273 	global $wp_query, $wp_rewrite;
   299 	global $wp_query, $wp_rewrite;
   274 
   300 
   275 	$queried_object = $wp_query->get_queried_object();
   301 	$queried_object    = $wp_query->get_queried_object();
   276 	$queried_object_id = (int) $wp_query->queried_object_id;
   302 	$queried_object_id = (int) $wp_query->queried_object_id;
   277 
   303 
   278 	$active_object = '';
   304 	$active_object               = '';
   279 	$active_ancestor_item_ids = array();
   305 	$active_ancestor_item_ids    = array();
   280 	$active_parent_item_ids = array();
   306 	$active_parent_item_ids      = array();
   281 	$active_parent_object_ids = array();
   307 	$active_parent_object_ids    = array();
   282 	$possible_taxonomy_ancestors = array();
   308 	$possible_taxonomy_ancestors = array();
   283 	$possible_object_parents = array();
   309 	$possible_object_parents     = array();
   284 	$home_page_id = (int) get_option( 'page_for_posts' );
   310 	$home_page_id                = (int) get_option( 'page_for_posts' );
   285 
   311 
   286 	if ( $wp_query->is_singular && ! empty( $queried_object->post_type ) && ! is_post_type_hierarchical( $queried_object->post_type ) ) {
   312 	if ( $wp_query->is_singular && ! empty( $queried_object->post_type ) && ! is_post_type_hierarchical( $queried_object->post_type ) ) {
   287 		foreach ( (array) get_object_taxonomies( $queried_object->post_type ) as $taxonomy ) {
   313 		foreach ( (array) get_object_taxonomies( $queried_object->post_type ) as $taxonomy ) {
   288 			if ( is_taxonomy_hierarchical( $taxonomy ) ) {
   314 			if ( is_taxonomy_hierarchical( $taxonomy ) ) {
   289 				$term_hierarchy = _get_term_hierarchy( $taxonomy );
   315 				$term_hierarchy = _get_term_hierarchy( $taxonomy );
   290 				$terms = wp_get_object_terms( $queried_object_id, $taxonomy, array( 'fields' => 'ids' ) );
   316 				$terms          = wp_get_object_terms( $queried_object_id, $taxonomy, array( 'fields' => 'ids' ) );
   291 				if ( is_array( $terms ) ) {
   317 				if ( is_array( $terms ) ) {
   292 					$possible_object_parents = array_merge( $possible_object_parents, $terms );
   318 					$possible_object_parents = array_merge( $possible_object_parents, $terms );
   293 					$term_to_ancestor = array();
   319 					$term_to_ancestor        = array();
   294 					foreach ( (array) $term_hierarchy as $anc => $descs ) {
   320 					foreach ( (array) $term_hierarchy as $anc => $descs ) {
   295 						foreach ( (array) $descs as $desc )
   321 						foreach ( (array) $descs as $desc ) {
   296 							$term_to_ancestor[ $desc ] = $anc;
   322 							$term_to_ancestor[ $desc ] = $anc;
       
   323 						}
   297 					}
   324 					}
   298 
   325 
   299 					foreach ( $terms as $desc ) {
   326 					foreach ( $terms as $desc ) {
   300 						do {
   327 						do {
   301 							$possible_taxonomy_ancestors[ $taxonomy ][] = $desc;
   328 							$possible_taxonomy_ancestors[ $taxonomy ][] = $desc;
   310 					}
   337 					}
   311 				}
   338 				}
   312 			}
   339 			}
   313 		}
   340 		}
   314 	} elseif ( ! empty( $queried_object->taxonomy ) && is_taxonomy_hierarchical( $queried_object->taxonomy ) ) {
   341 	} elseif ( ! empty( $queried_object->taxonomy ) && is_taxonomy_hierarchical( $queried_object->taxonomy ) ) {
   315 		$term_hierarchy = _get_term_hierarchy( $queried_object->taxonomy );
   342 		$term_hierarchy   = _get_term_hierarchy( $queried_object->taxonomy );
   316 		$term_to_ancestor = array();
   343 		$term_to_ancestor = array();
   317 		foreach ( (array) $term_hierarchy as $anc => $descs ) {
   344 		foreach ( (array) $term_hierarchy as $anc => $descs ) {
   318 			foreach ( (array) $descs as $desc )
   345 			foreach ( (array) $descs as $desc ) {
   319 				$term_to_ancestor[ $desc ] = $anc;
   346 				$term_to_ancestor[ $desc ] = $anc;
       
   347 			}
   320 		}
   348 		}
   321 		$desc = $queried_object->term_id;
   349 		$desc = $queried_object->term_id;
   322 		do {
   350 		do {
   323 			$possible_taxonomy_ancestors[ $queried_object->taxonomy ][] = $desc;
   351 			$possible_taxonomy_ancestors[ $queried_object->taxonomy ][] = $desc;
   324 			if ( isset( $term_to_ancestor[ $desc ] ) ) {
   352 			if ( isset( $term_to_ancestor[ $desc ] ) ) {
   331 		} while ( ! empty( $desc ) );
   359 		} while ( ! empty( $desc ) );
   332 	}
   360 	}
   333 
   361 
   334 	$possible_object_parents = array_filter( $possible_object_parents );
   362 	$possible_object_parents = array_filter( $possible_object_parents );
   335 
   363 
   336 	$front_page_url = home_url();
   364 	$front_page_url         = home_url();
   337 	$front_page_id  = (int) get_option( 'page_on_front' );
   365 	$front_page_id          = (int) get_option( 'page_on_front' );
       
   366 	$privacy_policy_page_id = (int) get_option( 'wp_page_for_privacy_policy' );
   338 
   367 
   339 	foreach ( (array) $menu_items as $key => $menu_item ) {
   368 	foreach ( (array) $menu_items as $key => $menu_item ) {
   340 
   369 
   341 		$menu_items[$key]->current = false;
   370 		$menu_items[ $key ]->current = false;
   342 
   371 
   343 		$classes = (array) $menu_item->classes;
   372 		$classes   = (array) $menu_item->classes;
   344 		$classes[] = 'menu-item';
   373 		$classes[] = 'menu-item';
   345 		$classes[] = 'menu-item-type-' . $menu_item->type;
   374 		$classes[] = 'menu-item-type-' . $menu_item->type;
   346 		$classes[] = 'menu-item-object-' . $menu_item->object;
   375 		$classes[] = 'menu-item-object-' . $menu_item->object;
   347 
   376 
   348 		// This menu item is set as the 'Front Page'.
   377 		// This menu item is set as the 'Front Page'.
   349 		if ( 'post_type' === $menu_item->type && $front_page_id === (int) $menu_item->object_id ) {
   378 		if ( 'post_type' === $menu_item->type && $front_page_id === (int) $menu_item->object_id ) {
   350 			$classes[] = 'menu-item-home';
   379 			$classes[] = 'menu-item-home';
   351 		}
   380 		}
   352 
   381 
       
   382 		// This menu item is set as the 'Privacy Policy Page'.
       
   383 		if ( 'post_type' === $menu_item->type && $privacy_policy_page_id === (int) $menu_item->object_id ) {
       
   384 			$classes[] = 'menu-item-privacy-policy';
       
   385 		}
       
   386 
   353 		// if the menu item corresponds to a taxonomy term for the currently-queried non-hierarchical post object
   387 		// if the menu item corresponds to a taxonomy term for the currently-queried non-hierarchical post object
   354 		if ( $wp_query->is_singular && 'taxonomy' == $menu_item->type && in_array( $menu_item->object_id, $possible_object_parents ) ) {
   388 		if ( $wp_query->is_singular && 'taxonomy' == $menu_item->type && in_array( $menu_item->object_id, $possible_object_parents ) ) {
   355 			$active_parent_object_ids[] = (int) $menu_item->object_id;
   389 			$active_parent_object_ids[] = (int) $menu_item->object_id;
   356 			$active_parent_item_ids[] = (int) $menu_item->db_id;
   390 			$active_parent_item_ids[]   = (int) $menu_item->db_id;
   357 			$active_object = $queried_object->post_type;
   391 			$active_object              = $queried_object->post_type;
   358 
   392 
   359 		// if the menu item corresponds to the currently-queried post or taxonomy object
   393 			// if the menu item corresponds to the currently-queried post or taxonomy object
   360 		} elseif (
   394 		} elseif (
   361 			$menu_item->object_id == $queried_object_id &&
   395 			$menu_item->object_id == $queried_object_id &&
   362 			(
   396 			(
   363 				( ! empty( $home_page_id ) && 'post_type' == $menu_item->type && $wp_query->is_home && $home_page_id == $menu_item->object_id ) ||
   397 				( ! empty( $home_page_id ) && 'post_type' == $menu_item->type && $wp_query->is_home && $home_page_id == $menu_item->object_id ) ||
   364 				( 'post_type' == $menu_item->type && $wp_query->is_singular ) ||
   398 				( 'post_type' == $menu_item->type && $wp_query->is_singular ) ||
   365 				( 'taxonomy' == $menu_item->type && ( $wp_query->is_category || $wp_query->is_tag || $wp_query->is_tax ) && $queried_object->taxonomy == $menu_item->object )
   399 				( 'taxonomy' == $menu_item->type && ( $wp_query->is_category || $wp_query->is_tag || $wp_query->is_tax ) && $queried_object->taxonomy == $menu_item->object )
   366 			)
   400 			)
   367 		) {
   401 		) {
   368 			$classes[] = 'current-menu-item';
   402 			$classes[]                   = 'current-menu-item';
   369 			$menu_items[$key]->current = true;
   403 			$menu_items[ $key ]->current = true;
   370 			$_anc_id = (int) $menu_item->db_id;
   404 			$_anc_id                     = (int) $menu_item->db_id;
   371 
   405 
   372 			while(
   406 			while (
   373 				( $_anc_id = get_post_meta( $_anc_id, '_menu_item_menu_item_parent', true ) ) &&
   407 				( $_anc_id = get_post_meta( $_anc_id, '_menu_item_menu_item_parent', true ) ) &&
   374 				! in_array( $_anc_id, $active_ancestor_item_ids )
   408 				! in_array( $_anc_id, $active_ancestor_item_ids )
   375 			) {
   409 			) {
   376 				$active_ancestor_item_ids[] = $_anc_id;
   410 				$active_ancestor_item_ids[] = $_anc_id;
   377 			}
   411 			}
   381 				$classes[] = 'page_item';
   415 				$classes[] = 'page_item';
   382 				$classes[] = 'page-item-' . $menu_item->object_id;
   416 				$classes[] = 'page-item-' . $menu_item->object_id;
   383 				$classes[] = 'current_page_item';
   417 				$classes[] = 'current_page_item';
   384 			}
   418 			}
   385 
   419 
   386 			$active_parent_item_ids[] = (int) $menu_item->menu_item_parent;
   420 			$active_parent_item_ids[]   = (int) $menu_item->menu_item_parent;
   387 			$active_parent_object_ids[] = (int) $menu_item->post_parent;
   421 			$active_parent_object_ids[] = (int) $menu_item->post_parent;
   388 			$active_object = $menu_item->object;
   422 			$active_object              = $menu_item->object;
   389 
   423 
   390 		// if the menu item corresponds to the currently-queried post type archive
   424 			// if the menu item corresponds to the currently-queried post type archive
   391 		} elseif (
   425 		} elseif (
   392 			'post_type_archive' == $menu_item->type &&
   426 			'post_type_archive' == $menu_item->type &&
   393 			is_post_type_archive( array( $menu_item->object ) )
   427 			is_post_type_archive( array( $menu_item->object ) )
   394 		) {
   428 		) {
   395 			$classes[] = 'current-menu-item';
   429 			$classes[]                   = 'current-menu-item';
   396 			$menu_items[$key]->current = true;
   430 			$menu_items[ $key ]->current = true;
   397 			$_anc_id = (int) $menu_item->db_id;
   431 			$_anc_id                     = (int) $menu_item->db_id;
   398 
   432 
   399 			while(
   433 			while (
   400 				( $_anc_id = get_post_meta( $_anc_id, '_menu_item_menu_item_parent', true ) ) &&
   434 				( $_anc_id = get_post_meta( $_anc_id, '_menu_item_menu_item_parent', true ) ) &&
   401 				! in_array( $_anc_id, $active_ancestor_item_ids )
   435 				! in_array( $_anc_id, $active_ancestor_item_ids )
   402 			) {
   436 			) {
   403 				$active_ancestor_item_ids[] = $_anc_id;
   437 				$active_ancestor_item_ids[] = $_anc_id;
   404 			}
   438 			}
   405 
   439 
   406 			$active_parent_item_ids[] = (int) $menu_item->menu_item_parent;
   440 			$active_parent_item_ids[] = (int) $menu_item->menu_item_parent;
   407 
   441 
   408 		// if the menu item corresponds to the currently-requested URL
   442 			// if the menu item corresponds to the currently-requested URL
   409 		} elseif ( 'custom' == $menu_item->object && isset( $_SERVER['HTTP_HOST'] ) ) {
   443 		} elseif ( 'custom' == $menu_item->object && isset( $_SERVER['HTTP_HOST'] ) ) {
   410 			$_root_relative_current = untrailingslashit( $_SERVER['REQUEST_URI'] );
   444 			$_root_relative_current = untrailingslashit( $_SERVER['REQUEST_URI'] );
   411 
   445 
   412 			//if it is the customize page then it will strips the query var off the url before entering the comparison block.
   446 			//if it is the customize page then it will strips the query var off the url before entering the comparison block.
   413 			if ( is_customize_preview() ) {
   447 			if ( is_customize_preview() ) {
   414 				$_root_relative_current = strtok( untrailingslashit( $_SERVER['REQUEST_URI'] ), '?' );
   448 				$_root_relative_current = strtok( untrailingslashit( $_SERVER['REQUEST_URI'] ), '?' );
   415 			}
   449 			}
   416 			$current_url = set_url_scheme( 'http://' . $_SERVER['HTTP_HOST'] . $_root_relative_current );
   450 
   417 			$raw_item_url = strpos( $menu_item->url, '#' ) ? substr( $menu_item->url, 0, strpos( $menu_item->url, '#' ) ) : $menu_item->url;
   451 			$current_url        = set_url_scheme( 'http://' . $_SERVER['HTTP_HOST'] . $_root_relative_current );
   418 			$item_url = set_url_scheme( untrailingslashit( $raw_item_url ) );
   452 			$raw_item_url       = strpos( $menu_item->url, '#' ) ? substr( $menu_item->url, 0, strpos( $menu_item->url, '#' ) ) : $menu_item->url;
       
   453 			$item_url           = set_url_scheme( untrailingslashit( $raw_item_url ) );
   419 			$_indexless_current = untrailingslashit( preg_replace( '/' . preg_quote( $wp_rewrite->index, '/' ) . '$/', '', $current_url ) );
   454 			$_indexless_current = untrailingslashit( preg_replace( '/' . preg_quote( $wp_rewrite->index, '/' ) . '$/', '', $current_url ) );
   420 
   455 
   421 			if ( $raw_item_url && in_array( $item_url, array( $current_url, $_indexless_current, $_root_relative_current ) ) ) {
   456 			$matches = array(
   422 				$classes[] = 'current-menu-item';
   457 				$current_url,
   423 				$menu_items[$key]->current = true;
   458 				urldecode( $current_url ),
   424 				$_anc_id = (int) $menu_item->db_id;
   459 				$_indexless_current,
   425 
   460 				urldecode( $_indexless_current ),
   426 				while(
   461 				$_root_relative_current,
       
   462 				urldecode( $_root_relative_current ),
       
   463 			);
       
   464 
       
   465 			if ( $raw_item_url && in_array( $item_url, $matches ) ) {
       
   466 				$classes[]                   = 'current-menu-item';
       
   467 				$menu_items[ $key ]->current = true;
       
   468 				$_anc_id                     = (int) $menu_item->db_id;
       
   469 
       
   470 				while (
   427 					( $_anc_id = get_post_meta( $_anc_id, '_menu_item_menu_item_parent', true ) ) &&
   471 					( $_anc_id = get_post_meta( $_anc_id, '_menu_item_menu_item_parent', true ) ) &&
   428 					! in_array( $_anc_id, $active_ancestor_item_ids )
   472 					! in_array( $_anc_id, $active_ancestor_item_ids )
   429 				) {
   473 				) {
   430 					$active_ancestor_item_ids[] = $_anc_id;
   474 					$active_ancestor_item_ids[] = $_anc_id;
   431 				}
   475 				}
   432 
   476 
   433 				if ( in_array( home_url(), array( untrailingslashit( $current_url ), untrailingslashit( $_indexless_current ) ) ) ) {
   477 				if ( in_array( home_url(), array( untrailingslashit( $current_url ), untrailingslashit( $_indexless_current ) ) ) ) {
   434 					// Back compat for home link to match wp_page_menu()
   478 					// Back compat for home link to match wp_page_menu()
   435 					$classes[] = 'current_page_item';
   479 					$classes[] = 'current_page_item';
   436 				}
   480 				}
   437 				$active_parent_item_ids[] = (int) $menu_item->menu_item_parent;
   481 				$active_parent_item_ids[]   = (int) $menu_item->menu_item_parent;
   438 				$active_parent_object_ids[] = (int) $menu_item->post_parent;
   482 				$active_parent_object_ids[] = (int) $menu_item->post_parent;
   439 				$active_object = $menu_item->object;
   483 				$active_object              = $menu_item->object;
   440 
   484 
   441 			// give front page item current-menu-item class when extra query arguments involved
   485 				// give front page item current-menu-item class when extra query arguments involved
   442 			} elseif ( $item_url == $front_page_url && is_front_page() ) {
   486 			} elseif ( $item_url == $front_page_url && is_front_page() ) {
   443 				$classes[] = 'current-menu-item';
   487 				$classes[] = 'current-menu-item';
   444 			}
   488 			}
   445 
   489 
   446 			if ( untrailingslashit($item_url) == home_url() )
   490 			if ( untrailingslashit( $item_url ) == home_url() ) {
   447 				$classes[] = 'menu-item-home';
   491 				$classes[] = 'menu-item-home';
       
   492 			}
   448 		}
   493 		}
   449 
   494 
   450 		// back-compat with wp_page_menu: add "current_page_parent" to static home page link for any non-page query
   495 		// back-compat with wp_page_menu: add "current_page_parent" to static home page link for any non-page query
   451 		if ( ! empty( $home_page_id ) && 'post_type' == $menu_item->type && empty( $wp_query->is_page ) && $home_page_id == $menu_item->object_id )
   496 		if ( ! empty( $home_page_id ) && 'post_type' == $menu_item->type && empty( $wp_query->is_page ) && $home_page_id == $menu_item->object_id ) {
   452 			$classes[] = 'current_page_parent';
   497 			$classes[] = 'current_page_parent';
   453 
   498 		}
   454 		$menu_items[$key]->classes = array_unique( $classes );
   499 
       
   500 		$menu_items[ $key ]->classes = array_unique( $classes );
   455 	}
   501 	}
   456 	$active_ancestor_item_ids = array_filter( array_unique( $active_ancestor_item_ids ) );
   502 	$active_ancestor_item_ids = array_filter( array_unique( $active_ancestor_item_ids ) );
   457 	$active_parent_item_ids = array_filter( array_unique( $active_parent_item_ids ) );
   503 	$active_parent_item_ids   = array_filter( array_unique( $active_parent_item_ids ) );
   458 	$active_parent_object_ids = array_filter( array_unique( $active_parent_object_ids ) );
   504 	$active_parent_object_ids = array_filter( array_unique( $active_parent_object_ids ) );
   459 
   505 
   460 	// set parent's class
   506 	// set parent's class
   461 	foreach ( (array) $menu_items as $key => $parent_item ) {
   507 	foreach ( (array) $menu_items as $key => $parent_item ) {
   462 		$classes = (array) $parent_item->classes;
   508 		$classes                                   = (array) $parent_item->classes;
   463 		$menu_items[$key]->current_item_ancestor = false;
   509 		$menu_items[ $key ]->current_item_ancestor = false;
   464 		$menu_items[$key]->current_item_parent = false;
   510 		$menu_items[ $key ]->current_item_parent   = false;
   465 
   511 
   466 		if (
   512 		if (
   467 			isset( $parent_item->type ) &&
   513 			isset( $parent_item->type ) &&
   468 			(
   514 			(
   469 				// ancestral post object
   515 				// ancestral post object
   488 			)
   534 			)
   489 		) {
   535 		) {
   490 			$classes[] = empty( $queried_object->taxonomy ) ? 'current-' . $queried_object->post_type . '-ancestor' : 'current-' . $queried_object->taxonomy . '-ancestor';
   536 			$classes[] = empty( $queried_object->taxonomy ) ? 'current-' . $queried_object->post_type . '-ancestor' : 'current-' . $queried_object->taxonomy . '-ancestor';
   491 		}
   537 		}
   492 
   538 
   493 		if ( in_array(  intval( $parent_item->db_id ), $active_ancestor_item_ids ) ) {
   539 		if ( in_array( intval( $parent_item->db_id ), $active_ancestor_item_ids ) ) {
   494 			$classes[] = 'current-menu-ancestor';
   540 			$classes[]                                 = 'current-menu-ancestor';
   495 			$menu_items[$key]->current_item_ancestor = true;
   541 			$menu_items[ $key ]->current_item_ancestor = true;
   496 		}
   542 		}
   497 		if ( in_array( $parent_item->db_id, $active_parent_item_ids ) ) {
   543 		if ( in_array( $parent_item->db_id, $active_parent_item_ids ) ) {
   498 			$classes[] = 'current-menu-parent';
   544 			$classes[]                               = 'current-menu-parent';
   499 			$menu_items[$key]->current_item_parent = true;
   545 			$menu_items[ $key ]->current_item_parent = true;
   500 		}
   546 		}
   501 		if ( in_array( $parent_item->object_id, $active_parent_object_ids ) )
   547 		if ( in_array( $parent_item->object_id, $active_parent_object_ids ) ) {
   502 			$classes[] = 'current-' . $active_object . '-parent';
   548 			$classes[] = 'current-' . $active_object . '-parent';
       
   549 		}
   503 
   550 
   504 		if ( 'post_type' == $parent_item->type && 'page' == $parent_item->object ) {
   551 		if ( 'post_type' == $parent_item->type && 'page' == $parent_item->object ) {
   505 			// Back compat classes for pages to match wp_page_menu()
   552 			// Back compat classes for pages to match wp_page_menu()
   506 			if ( in_array('current-menu-parent', $classes) )
   553 			if ( in_array( 'current-menu-parent', $classes ) ) {
   507 				$classes[] = 'current_page_parent';
   554 				$classes[] = 'current_page_parent';
   508 			if ( in_array('current-menu-ancestor', $classes) )
   555 			}
       
   556 			if ( in_array( 'current-menu-ancestor', $classes ) ) {
   509 				$classes[] = 'current_page_ancestor';
   557 				$classes[] = 'current_page_ancestor';
   510 		}
   558 			}
   511 
   559 		}
   512 		$menu_items[$key]->classes = array_unique( $classes );
   560 
       
   561 		$menu_items[ $key ]->classes = array_unique( $classes );
   513 	}
   562 	}
   514 }
   563 }
   515 
   564 
   516 /**
   565 /**
   517  * Retrieve the HTML list content for nav menu items.
   566  * Retrieve the HTML list content for nav menu items.
   523  * @param int      $depth Depth of the item in reference to parents.
   572  * @param int      $depth Depth of the item in reference to parents.
   524  * @param stdClass $r     An object containing wp_nav_menu() arguments.
   573  * @param stdClass $r     An object containing wp_nav_menu() arguments.
   525  * @return string The HTML list content for the menu items.
   574  * @return string The HTML list content for the menu items.
   526  */
   575  */
   527 function walk_nav_menu_tree( $items, $depth, $r ) {
   576 function walk_nav_menu_tree( $items, $depth, $r ) {
   528 	$walker = ( empty($r->walker) ) ? new Walker_Nav_Menu : $r->walker;
   577 	$walker = ( empty( $r->walker ) ) ? new Walker_Nav_Menu : $r->walker;
   529 	$args = array( $items, $depth, $r );
   578 	$args   = array( $items, $depth, $r );
   530 
   579 
   531 	return call_user_func_array( array( $walker, 'walk' ), $args );
   580 	return call_user_func_array( array( $walker, 'walk' ), $args );
   532 }
   581 }
   533 
   582 
   534 /**
   583 /**