wp/wp-includes/nav-menu-template.php
changeset 7 cf61fcea0001
parent 5 5e2f62d02dcd
child 9 177826044cd9
equal deleted inserted replaced
6:490d5cc509ed 7:cf61fcea0001
     1 <?php
     1 <?php
     2 /**
     2 /**
     3  * Navigation Menu template functions
     3  * Nav Menu API: Template functions
     4  *
     4  *
     5  * @package WordPress
     5  * @package WordPress
     6  * @subpackage Nav_Menus
     6  * @subpackage Nav_Menus
     7  * @since 3.0.0
     7  * @since 3.0.0
     8  */
     8  */
     9 
     9 
    10 /**
    10 /** Walker_Nav_Menu class */
    11  * Create HTML list of nav menu items.
    11 require_once ABSPATH . WPINC . '/class-walker-nav-menu.php';
    12  *
       
    13  * @since 3.0.0
       
    14  * @uses Walker
       
    15  */
       
    16 class Walker_Nav_Menu extends Walker {
       
    17 	/**
       
    18 	 * What the class handles.
       
    19 	 *
       
    20 	 * @see Walker::$tree_type
       
    21 	 * @since 3.0.0
       
    22 	 * @var string
       
    23 	 */
       
    24 	public $tree_type = array( 'post_type', 'taxonomy', 'custom' );
       
    25 
       
    26 	/**
       
    27 	 * Database fields to use.
       
    28 	 *
       
    29 	 * @see Walker::$db_fields
       
    30 	 * @since 3.0.0
       
    31 	 * @todo Decouple this.
       
    32 	 * @var array
       
    33 	 */
       
    34 	public $db_fields = array( 'parent' => 'menu_item_parent', 'id' => 'db_id' );
       
    35 
       
    36 	/**
       
    37 	 * Starts the list before the elements are added.
       
    38 	 *
       
    39 	 * @see Walker::start_lvl()
       
    40 	 *
       
    41 	 * @since 3.0.0
       
    42 	 *
       
    43 	 * @param string $output Passed by reference. Used to append additional content.
       
    44 	 * @param int    $depth  Depth of menu item. Used for padding.
       
    45 	 * @param array  $args   An array of arguments. @see wp_nav_menu()
       
    46 	 */
       
    47 	public function start_lvl( &$output, $depth = 0, $args = array() ) {
       
    48 		$indent = str_repeat("\t", $depth);
       
    49 		$output .= "\n$indent<ul class=\"sub-menu\">\n";
       
    50 	}
       
    51 
       
    52 	/**
       
    53 	 * Ends the list of after the elements are added.
       
    54 	 *
       
    55 	 * @see Walker::end_lvl()
       
    56 	 *
       
    57 	 * @since 3.0.0
       
    58 	 *
       
    59 	 * @param string $output Passed by reference. Used to append additional content.
       
    60 	 * @param int    $depth  Depth of menu item. Used for padding.
       
    61 	 * @param array  $args   An array of arguments. @see wp_nav_menu()
       
    62 	 */
       
    63 	public function end_lvl( &$output, $depth = 0, $args = array() ) {
       
    64 		$indent = str_repeat("\t", $depth);
       
    65 		$output .= "$indent</ul>\n";
       
    66 	}
       
    67 
       
    68 	/**
       
    69 	 * Start the element output.
       
    70 	 *
       
    71 	 * @see Walker::start_el()
       
    72 	 *
       
    73 	 * @since 3.0.0
       
    74 	 *
       
    75 	 * @param string $output Passed by reference. Used to append additional content.
       
    76 	 * @param object $item   Menu item data object.
       
    77 	 * @param int    $depth  Depth of menu item. Used for padding.
       
    78 	 * @param array  $args   An array of arguments. @see wp_nav_menu()
       
    79 	 * @param int    $id     Current item ID.
       
    80 	 */
       
    81 	public function start_el( &$output, $item, $depth = 0, $args = array(), $id = 0 ) {
       
    82 		$indent = ( $depth ) ? str_repeat( "\t", $depth ) : '';
       
    83 
       
    84 		$classes = empty( $item->classes ) ? array() : (array) $item->classes;
       
    85 		$classes[] = 'menu-item-' . $item->ID;
       
    86 
       
    87 		/**
       
    88 		 * Filter the CSS class(es) applied to a menu item's list item element.
       
    89 		 *
       
    90 		 * @since 3.0.0
       
    91 		 * @since 4.1.0 The `$depth` parameter was added.
       
    92 		 *
       
    93 		 * @param array  $classes The CSS classes that are applied to the menu item's `<li>` element.
       
    94 		 * @param object $item    The current menu item.
       
    95 		 * @param array  $args    An array of {@see wp_nav_menu()} arguments.
       
    96 		 * @param int    $depth   Depth of menu item. Used for padding.
       
    97 		 */
       
    98 		$class_names = join( ' ', apply_filters( 'nav_menu_css_class', array_filter( $classes ), $item, $args, $depth ) );
       
    99 		$class_names = $class_names ? ' class="' . esc_attr( $class_names ) . '"' : '';
       
   100 
       
   101 		/**
       
   102 		 * Filter the ID applied to a menu item's list item element.
       
   103 		 *
       
   104 		 * @since 3.0.1
       
   105 		 * @since 4.1.0 The `$depth` parameter was added.
       
   106 		 *
       
   107 		 * @param string $menu_id The ID that is applied to the menu item's `<li>` element.
       
   108 		 * @param object $item    The current menu item.
       
   109 		 * @param array  $args    An array of {@see wp_nav_menu()} arguments.
       
   110 		 * @param int    $depth   Depth of menu item. Used for padding.
       
   111 		 */
       
   112 		$id = apply_filters( 'nav_menu_item_id', 'menu-item-'. $item->ID, $item, $args, $depth );
       
   113 		$id = $id ? ' id="' . esc_attr( $id ) . '"' : '';
       
   114 
       
   115 		$output .= $indent . '<li' . $id . $class_names .'>';
       
   116 
       
   117 		$atts = array();
       
   118 		$atts['title']  = ! empty( $item->attr_title ) ? $item->attr_title : '';
       
   119 		$atts['target'] = ! empty( $item->target )     ? $item->target     : '';
       
   120 		$atts['rel']    = ! empty( $item->xfn )        ? $item->xfn        : '';
       
   121 		$atts['href']   = ! empty( $item->url )        ? $item->url        : '';
       
   122 
       
   123 		/**
       
   124 		 * Filter the HTML attributes applied to a menu item's anchor element.
       
   125 		 *
       
   126 		 * @since 3.6.0
       
   127 		 * @since 4.1.0 The `$depth` parameter was added.
       
   128 		 *
       
   129 		 * @param array $atts {
       
   130 		 *     The HTML attributes applied to the menu item's `<a>` element, empty strings are ignored.
       
   131 		 *
       
   132 		 *     @type string $title  Title attribute.
       
   133 		 *     @type string $target Target attribute.
       
   134 		 *     @type string $rel    The rel attribute.
       
   135 		 *     @type string $href   The href attribute.
       
   136 		 * }
       
   137 		 * @param object $item  The current menu item.
       
   138 		 * @param array  $args  An array of {@see wp_nav_menu()} arguments.
       
   139 		 * @param int    $depth Depth of menu item. Used for padding.
       
   140 		 */
       
   141 		$atts = apply_filters( 'nav_menu_link_attributes', $atts, $item, $args, $depth );
       
   142 
       
   143 		$attributes = '';
       
   144 		foreach ( $atts as $attr => $value ) {
       
   145 			if ( ! empty( $value ) ) {
       
   146 				$value = ( 'href' === $attr ) ? esc_url( $value ) : esc_attr( $value );
       
   147 				$attributes .= ' ' . $attr . '="' . $value . '"';
       
   148 			}
       
   149 		}
       
   150 
       
   151 		$item_output = $args->before;
       
   152 		$item_output .= '<a'. $attributes .'>';
       
   153 		/** This filter is documented in wp-includes/post-template.php */
       
   154 		$item_output .= $args->link_before . apply_filters( 'the_title', $item->title, $item->ID ) . $args->link_after;
       
   155 		$item_output .= '</a>';
       
   156 		$item_output .= $args->after;
       
   157 
       
   158 		/**
       
   159 		 * Filter a menu item's starting output.
       
   160 		 *
       
   161 		 * The menu item's starting output only includes `$args->before`, the opening `<a>`,
       
   162 		 * the menu item's title, the closing `</a>`, and `$args->after`. Currently, there is
       
   163 		 * no filter for modifying the opening and closing `<li>` for a menu item.
       
   164 		 *
       
   165 		 * @since 3.0.0
       
   166 		 *
       
   167 		 * @param string $item_output The menu item's starting HTML output.
       
   168 		 * @param object $item        Menu item data object.
       
   169 		 * @param int    $depth       Depth of menu item. Used for padding.
       
   170 		 * @param array  $args        An array of {@see wp_nav_menu()} arguments.
       
   171 		 */
       
   172 		$output .= apply_filters( 'walker_nav_menu_start_el', $item_output, $item, $depth, $args );
       
   173 	}
       
   174 
       
   175 	/**
       
   176 	 * Ends the element output, if needed.
       
   177 	 *
       
   178 	 * @see Walker::end_el()
       
   179 	 *
       
   180 	 * @since 3.0.0
       
   181 	 *
       
   182 	 * @param string $output Passed by reference. Used to append additional content.
       
   183 	 * @param object $item   Page data object. Not used.
       
   184 	 * @param int    $depth  Depth of page. Not Used.
       
   185 	 * @param array  $args   An array of arguments. @see wp_nav_menu()
       
   186 	 */
       
   187 	public function end_el( &$output, $item, $depth = 0, $args = array() ) {
       
   188 		$output .= "</li>\n";
       
   189 	}
       
   190 
       
   191 } // Walker_Nav_Menu
       
   192 
    12 
   193 /**
    13 /**
   194  * Displays a navigation menu.
    14  * Displays a navigation menu.
   195  *
    15  *
   196  * @since 3.0.0
    16  * @since 3.0.0
       
    17  * @since 4.7.0 Added the `item_spacing` argument.
       
    18  *
       
    19  * @staticvar array $menu_id_slugs
   197  *
    20  *
   198  * @param array $args {
    21  * @param array $args {
   199  *     Optional. Array of nav menu arguments.
    22  *     Optional. Array of nav menu arguments.
   200  *
    23  *
   201  *     @type string        $menu            Desired menu. Accepts (matching in order) id, slug, name. Default empty.
    24  *     @type int|string|WP_Term $menu            Desired menu. Accepts a menu ID, slug, name, or object. Default empty.
   202  *     @type string        $menu_class      CSS class to use for the ul element which forms the menu. Default 'menu'.
    25  *     @type string             $menu_class      CSS class to use for the ul element which forms the menu. Default 'menu'.
   203  *     @type string        $menu_id         The ID that is applied to the ul element which forms the menu.
    26  *     @type string             $menu_id         The ID that is applied to the ul element which forms the menu.
   204  *                                          Default is the menu slug, incremented.
    27  *                                               Default is the menu slug, incremented.
   205  *     @type string        $container       Whether to wrap the ul, and what to wrap it with. Default 'div'.
    28  *     @type string             $container       Whether to wrap the ul, and what to wrap it with. Default 'div'.
   206  *     @type string        $container_class Class that is applied to the container. Default 'menu-{menu slug}-container'.
    29  *     @type string             $container_class Class that is applied to the container. Default 'menu-{menu slug}-container'.
   207  *     @type string        $container_id    The ID that is applied to the container. Default empty.
    30  *     @type string             $container_id    The ID that is applied to the container. Default empty.
   208  *     @type callback|bool $fallback_cb     If the menu doesn't exists, a callback function will fire.
    31  *     @type callable|bool      $fallback_cb     If the menu doesn't exists, a callback function will fire.
   209  *                                          Default is 'wp_page_menu'. Set to false for no fallback.
    32  *                                               Default is 'wp_page_menu'. Set to false for no fallback.
   210  *     @type string        $before          Text before the link text. Default empty.
    33  *     @type string             $before          Text before the link markup. Default empty.
   211  *     @type string        $after           Text after the link text. Default empty.
    34  *     @type string             $after           Text after the link markup. Default empty.
   212  *     @type string        $link_before     Text before the link. Default empty.
    35  *     @type string             $link_before     Text before the link text. Default empty.
   213  *     @type string        $link_after      Text after the link. Default empty.
    36  *     @type string             $link_after      Text after the link text. Default empty.
   214  *     @type bool          $echo            Whether to echo the menu or return it. Default true.
    37  *     @type bool               $echo            Whether to echo the menu or return it. Default true.
   215  *     @type int           $depth           How many levels of the hierarchy are to be included. 0 means all. Default 0.
    38  *     @type int                $depth           How many levels of the hierarchy are to be included. 0 means all. Default 0.
   216  *     @type object        $walker          Instance of a custom walker class. Default empty.
    39  *     @type object             $walker          Instance of a custom walker class. Default empty.
   217  *     @type string        $theme_location  Theme location to be used. Must be registered with register_nav_menu()
    40  *     @type string             $theme_location  Theme location to be used. Must be registered with register_nav_menu()
   218  *                                          in order to be selectable by the user.
    41  *                                               in order to be selectable by the user.
   219  *     @type string        $items_wrap      How the list items should be wrapped. Default is a ul with an id and class.
    42  *     @type string             $items_wrap      How the list items should be wrapped. Default is a ul with an id and class.
   220  *                                          Uses printf() format with numbered placeholders.
    43  *                                               Uses printf() format with numbered placeholders.
       
    44  *     @type string             $item_spacing    Whether to preserve whitespace within the menu's HTML. Accepts 'preserve' or 'discard'. Default 'preserve'.
   221  * }
    45  * }
   222  * @return mixed 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.
   223  */
    47  */
   224 function wp_nav_menu( $args = array() ) {
    48 function wp_nav_menu( $args = array() ) {
   225 	static $menu_id_slugs = array();
    49 	static $menu_id_slugs = array();
   226 
    50 
   227 	$defaults = array( 'menu' => '', 'container' => 'div', 'container_class' => '', 'container_id' => '', 'menu_class' => 'menu', 'menu_id' => '',
    51 	$defaults = array( 'menu' => '', 'container' => 'div', 'container_class' => '', 'container_id' => '', 'menu_class' => 'menu', 'menu_id' => '',
   228 	'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>',
    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',
   229 	'depth' => 0, 'walker' => '', 'theme_location' => '' );
    53 	'depth' => 0, 'walker' => '', 'theme_location' => '' );
   230 
    54 
   231 	$args = wp_parse_args( $args, $defaults );
    55 	$args = wp_parse_args( $args, $defaults );
       
    56 
       
    57 	if ( ! in_array( $args['item_spacing'], array( 'preserve', 'discard' ), true ) ) {
       
    58 		// invalid value, fall back to default.
       
    59 		$args['item_spacing'] = $defaults['item_spacing'];
       
    60 	}
       
    61 
   232 	/**
    62 	/**
   233 	 * Filter the arguments used to display a navigation menu.
    63 	 * Filters the arguments used to display a navigation menu.
   234 	 *
    64 	 *
   235 	 * @since 3.0.0
    65 	 * @since 3.0.0
   236 	 *
    66 	 *
   237 	 * @see wp_nav_menu()
    67 	 * @see wp_nav_menu()
   238 	 *
    68 	 *
   240 	 */
    70 	 */
   241 	$args = apply_filters( 'wp_nav_menu_args', $args );
    71 	$args = apply_filters( 'wp_nav_menu_args', $args );
   242 	$args = (object) $args;
    72 	$args = (object) $args;
   243 
    73 
   244 	/**
    74 	/**
   245 	 * Filter whether to short-circuit the wp_nav_menu() output.
    75 	 * Filters whether to short-circuit the wp_nav_menu() output.
   246 	 *
    76 	 *
   247 	 * Returning a non-null value to the filter will short-circuit
    77 	 * Returning a non-null value to the filter will short-circuit
   248 	 * wp_nav_menu(), echoing that value if $args->echo is true,
    78 	 * wp_nav_menu(), echoing that value if $args->echo is true,
   249 	 * returning that value otherwise.
    79 	 * returning that value otherwise.
   250 	 *
    80 	 *
   251 	 * @since 3.9.0
    81 	 * @since 3.9.0
   252 	 *
    82 	 *
   253 	 * @see wp_nav_menu()
    83 	 * @see wp_nav_menu()
   254 	 *
    84 	 *
   255 	 * @param string|null $output Nav menu output to short-circuit with. Default null.
    85 	 * @param string|null $output Nav menu output to short-circuit with. Default null.
   256 	 * @param object      $args   An object containing wp_nav_menu() arguments.
    86 	 * @param stdClass    $args   An object containing wp_nav_menu() arguments.
   257 	 */
    87 	 */
   258 	$nav_menu = apply_filters( 'pre_wp_nav_menu', null, $args );
    88 	$nav_menu = apply_filters( 'pre_wp_nav_menu', null, $args );
   259 
    89 
   260 	if ( null !== $nav_menu ) {
    90 	if ( null !== $nav_menu ) {
   261 		if ( $args->echo ) {
    91 		if ( $args->echo ) {
   282 				break;
   112 				break;
   283 			}
   113 			}
   284 		}
   114 		}
   285 	}
   115 	}
   286 
   116 
       
   117 	if ( empty( $args->menu ) ) {
       
   118 		$args->menu = $menu;
       
   119 	}
       
   120 
   287 	// If the menu exists, get its items.
   121 	// If the menu exists, get its items.
   288 	if ( $menu && ! is_wp_error($menu) && !isset($menu_items) )
   122 	if ( $menu && ! is_wp_error($menu) && !isset($menu_items) )
   289 		$menu_items = wp_get_nav_menu_items( $menu->term_id, array( 'update_post_term_cache' => false ) );
   123 		$menu_items = wp_get_nav_menu_items( $menu->term_id, array( 'update_post_term_cache' => false ) );
   290 
   124 
   291 	/*
   125 	/*
   295 	 * If no menu items were found:
   129 	 * If no menu items were found:
   296 	 *  - Fall back, but only if no theme location was specified.
   130 	 *  - Fall back, but only if no theme location was specified.
   297 	 *  - Otherwise, bail.
   131 	 *  - Otherwise, bail.
   298 	 */
   132 	 */
   299 	if ( ( !$menu || is_wp_error($menu) || ( isset($menu_items) && empty($menu_items) && !$args->theme_location ) )
   133 	if ( ( !$menu || is_wp_error($menu) || ( isset($menu_items) && empty($menu_items) && !$args->theme_location ) )
   300 		&& $args->fallback_cb && is_callable( $args->fallback_cb ) )
   134 		&& isset( $args->fallback_cb ) && $args->fallback_cb && is_callable( $args->fallback_cb ) )
   301 			return call_user_func( $args->fallback_cb, (array) $args );
   135 			return call_user_func( $args->fallback_cb, (array) $args );
   302 
   136 
   303 	if ( ! $menu || is_wp_error( $menu ) )
   137 	if ( ! $menu || is_wp_error( $menu ) )
   304 		return false;
   138 		return false;
   305 
   139 
   306 	$nav_menu = $items = '';
   140 	$nav_menu = $items = '';
   307 
   141 
   308 	$show_container = false;
   142 	$show_container = false;
   309 	if ( $args->container ) {
   143 	if ( $args->container ) {
   310 		/**
   144 		/**
   311 		 * Filter the list of HTML tags that are valid for use as menu containers.
   145 		 * Filters the list of HTML tags that are valid for use as menu containers.
   312 		 *
   146 		 *
   313 		 * @since 3.0.0
   147 		 * @since 3.0.0
   314 		 *
   148 		 *
   315 		 * @param array $tags The acceptable HTML tags for use as menu containers.
   149 		 * @param array $tags The acceptable HTML tags for use as menu containers.
   316 		 *                    Default is array containing 'div' and 'nav'.
   150 		 *                    Default is array containing 'div' and 'nav'.
   317 		 */
   151 		 */
   318 		$allowed_tags = apply_filters( 'wp_nav_menu_container_allowedtags', array( 'div', 'nav' ) );
   152 		$allowed_tags = apply_filters( 'wp_nav_menu_container_allowedtags', array( 'div', 'nav' ) );
   319 		if ( in_array( $args->container, $allowed_tags ) ) {
   153 		if ( is_string( $args->container ) && in_array( $args->container, $allowed_tags ) ) {
   320 			$show_container = true;
   154 			$show_container = true;
   321 			$class = $args->container_class ? ' class="' . esc_attr( $args->container_class ) . '"' : ' class="menu-'. $menu->slug .'-container"';
   155 			$class = $args->container_class ? ' class="' . esc_attr( $args->container_class ) . '"' : ' class="menu-'. $menu->slug .'-container"';
   322 			$id = $args->container_id ? ' id="' . esc_attr( $args->container_id ) . '"' : '';
   156 			$id = $args->container_id ? ' id="' . esc_attr( $args->container_id ) . '"' : '';
   323 			$nav_menu .= '<'. $args->container . $id . $class . '>';
   157 			$nav_menu .= '<'. $args->container . $id . $class . '>';
   324 		}
   158 		}
   343 	}
   177 	}
   344 
   178 
   345 	unset( $menu_items, $menu_item );
   179 	unset( $menu_items, $menu_item );
   346 
   180 
   347 	/**
   181 	/**
   348 	 * Filter the sorted list of menu item objects before generating the menu's HTML.
   182 	 * Filters the sorted list of menu item objects before generating the menu's HTML.
   349 	 *
   183 	 *
   350 	 * @since 3.1.0
   184 	 * @since 3.1.0
   351 	 *
   185 	 *
   352 	 * @param array  $sorted_menu_items The menu items, sorted by each menu item's menu order.
   186 	 * @param array    $sorted_menu_items The menu items, sorted by each menu item's menu order.
   353 	 * @param object $args              An object containing wp_nav_menu() arguments.
   187 	 * @param stdClass $args              An object containing wp_nav_menu() arguments.
   354 	 */
   188 	 */
   355 	$sorted_menu_items = apply_filters( 'wp_nav_menu_objects', $sorted_menu_items, $args );
   189 	$sorted_menu_items = apply_filters( 'wp_nav_menu_objects', $sorted_menu_items, $args );
   356 
   190 
   357 	$items .= walk_nav_menu_tree( $sorted_menu_items, $args->depth, $args );
   191 	$items .= walk_nav_menu_tree( $sorted_menu_items, $args->depth, $args );
   358 	unset($sorted_menu_items);
   192 	unset($sorted_menu_items);
   372 	$menu_id_slugs[] = $wrap_id;
   206 	$menu_id_slugs[] = $wrap_id;
   373 
   207 
   374 	$wrap_class = $args->menu_class ? $args->menu_class : '';
   208 	$wrap_class = $args->menu_class ? $args->menu_class : '';
   375 
   209 
   376 	/**
   210 	/**
   377 	 * Filter the HTML list content for navigation menus.
   211 	 * Filters the HTML list content for navigation menus.
   378 	 *
   212 	 *
   379 	 * @since 3.0.0
   213 	 * @since 3.0.0
   380 	 *
   214 	 *
   381 	 * @see wp_nav_menu()
   215 	 * @see wp_nav_menu()
   382 	 *
   216 	 *
   383 	 * @param string $items The HTML list content for the menu items.
   217 	 * @param string   $items The HTML list content for the menu items.
   384 	 * @param object $args  An object containing wp_nav_menu() arguments.
   218 	 * @param stdClass $args  An object containing wp_nav_menu() arguments.
   385 	 */
   219 	 */
   386 	$items = apply_filters( 'wp_nav_menu_items', $items, $args );
   220 	$items = apply_filters( 'wp_nav_menu_items', $items, $args );
   387 	/**
   221 	/**
   388 	 * Filter the HTML list content for a specific navigation menu.
   222 	 * Filters the HTML list content for a specific navigation menu.
   389 	 *
   223 	 *
   390 	 * @since 3.0.0
   224 	 * @since 3.0.0
   391 	 *
   225 	 *
   392 	 * @see wp_nav_menu()
   226 	 * @see wp_nav_menu()
   393 	 *
   227 	 *
   394 	 * @param string $items The HTML list content for the menu items.
   228 	 * @param string   $items The HTML list content for the menu items.
   395 	 * @param object $args  An object containing wp_nav_menu() arguments.
   229 	 * @param stdClass $args  An object containing wp_nav_menu() arguments.
   396 	 */
   230 	 */
   397 	$items = apply_filters( "wp_nav_menu_{$menu->slug}_items", $items, $args );
   231 	$items = apply_filters( "wp_nav_menu_{$menu->slug}_items", $items, $args );
   398 
   232 
   399 	// Don't print any markup if there are no items at this point.
   233 	// Don't print any markup if there are no items at this point.
   400 	if ( empty( $items ) )
   234 	if ( empty( $items ) )
   405 
   239 
   406 	if ( $show_container )
   240 	if ( $show_container )
   407 		$nav_menu .= '</' . $args->container . '>';
   241 		$nav_menu .= '</' . $args->container . '>';
   408 
   242 
   409 	/**
   243 	/**
   410 	 * Filter the HTML content for navigation menus.
   244 	 * Filters the HTML content for navigation menus.
   411 	 *
   245 	 *
   412 	 * @since 3.0.0
   246 	 * @since 3.0.0
   413 	 *
   247 	 *
   414 	 * @see wp_nav_menu()
   248 	 * @see wp_nav_menu()
   415 	 *
   249 	 *
   416 	 * @param string $nav_menu The HTML content for the navigation menu.
   250 	 * @param string   $nav_menu The HTML content for the navigation menu.
   417 	 * @param object $args     An object containing wp_nav_menu() arguments.
   251 	 * @param stdClass $args     An object containing wp_nav_menu() arguments.
   418 	 */
   252 	 */
   419 	$nav_menu = apply_filters( 'wp_nav_menu', $nav_menu, $args );
   253 	$nav_menu = apply_filters( 'wp_nav_menu', $nav_menu, $args );
   420 
   254 
   421 	if ( $args->echo )
   255 	if ( $args->echo )
   422 		echo $nav_menu;
   256 		echo $nav_menu;
   427 /**
   261 /**
   428  * Add the class property classes for the current context, if applicable.
   262  * Add the class property classes for the current context, if applicable.
   429  *
   263  *
   430  * @access private
   264  * @access private
   431  * @since 3.0.0
   265  * @since 3.0.0
       
   266  *
       
   267  * @global WP_Query   $wp_query
       
   268  * @global WP_Rewrite $wp_rewrite
   432  *
   269  *
   433  * @param array $menu_items The current menu item objects to which to add the class property information.
   270  * @param array $menu_items The current menu item objects to which to add the class property information.
   434  */
   271  */
   435 function _wp_menu_item_classes_by_context( &$menu_items ) {
   272 function _wp_menu_item_classes_by_context( &$menu_items ) {
   436 	global $wp_query, $wp_rewrite;
   273 	global $wp_query, $wp_rewrite;
   495 	}
   332 	}
   496 
   333 
   497 	$possible_object_parents = array_filter( $possible_object_parents );
   334 	$possible_object_parents = array_filter( $possible_object_parents );
   498 
   335 
   499 	$front_page_url = home_url();
   336 	$front_page_url = home_url();
       
   337 	$front_page_id  = (int) get_option( 'page_on_front' );
   500 
   338 
   501 	foreach ( (array) $menu_items as $key => $menu_item ) {
   339 	foreach ( (array) $menu_items as $key => $menu_item ) {
   502 
   340 
   503 		$menu_items[$key]->current = false;
   341 		$menu_items[$key]->current = false;
   504 
   342 
   505 		$classes = (array) $menu_item->classes;
   343 		$classes = (array) $menu_item->classes;
   506 		$classes[] = 'menu-item';
   344 		$classes[] = 'menu-item';
   507 		$classes[] = 'menu-item-type-' . $menu_item->type;
   345 		$classes[] = 'menu-item-type-' . $menu_item->type;
   508 		$classes[] = 'menu-item-object-' . $menu_item->object;
   346 		$classes[] = 'menu-item-object-' . $menu_item->object;
       
   347 
       
   348 		// This menu item is set as the 'Front Page'.
       
   349 		if ( 'post_type' === $menu_item->type && $front_page_id === (int) $menu_item->object_id ) {
       
   350 			$classes[] = 'menu-item-home';
       
   351 		}
   509 
   352 
   510 		// if the menu item corresponds to a taxonomy term for the currently-queried non-hierarchical post object
   353 		// if the menu item corresponds to a taxonomy term for the currently-queried non-hierarchical post object
   511 		if ( $wp_query->is_singular && 'taxonomy' == $menu_item->type && in_array( $menu_item->object_id, $possible_object_parents ) ) {
   354 		if ( $wp_query->is_singular && 'taxonomy' == $menu_item->type && in_array( $menu_item->object_id, $possible_object_parents ) ) {
   512 			$active_parent_object_ids[] = (int) $menu_item->object_id;
   355 			$active_parent_object_ids[] = (int) $menu_item->object_id;
   513 			$active_parent_item_ids[] = (int) $menu_item->db_id;
   356 			$active_parent_item_ids[] = (int) $menu_item->db_id;
   537 				// Back compat classes for pages to match wp_page_menu()
   380 				// Back compat classes for pages to match wp_page_menu()
   538 				$classes[] = 'page_item';
   381 				$classes[] = 'page_item';
   539 				$classes[] = 'page-item-' . $menu_item->object_id;
   382 				$classes[] = 'page-item-' . $menu_item->object_id;
   540 				$classes[] = 'current_page_item';
   383 				$classes[] = 'current_page_item';
   541 			}
   384 			}
       
   385 
   542 			$active_parent_item_ids[] = (int) $menu_item->menu_item_parent;
   386 			$active_parent_item_ids[] = (int) $menu_item->menu_item_parent;
   543 			$active_parent_object_ids[] = (int) $menu_item->post_parent;
   387 			$active_parent_object_ids[] = (int) $menu_item->post_parent;
   544 			$active_object = $menu_item->object;
   388 			$active_object = $menu_item->object;
   545 
   389 
       
   390 		// if the menu item corresponds to the currently-queried post type archive
       
   391 		} elseif (
       
   392 			'post_type_archive' == $menu_item->type &&
       
   393 			is_post_type_archive( array( $menu_item->object ) )
       
   394 		) {
       
   395 			$classes[] = 'current-menu-item';
       
   396 			$menu_items[$key]->current = true;
       
   397 			$_anc_id = (int) $menu_item->db_id;
       
   398 
       
   399 			while(
       
   400 				( $_anc_id = get_post_meta( $_anc_id, '_menu_item_menu_item_parent', true ) ) &&
       
   401 				! in_array( $_anc_id, $active_ancestor_item_ids )
       
   402 			) {
       
   403 				$active_ancestor_item_ids[] = $_anc_id;
       
   404 			}
       
   405 
       
   406 			$active_parent_item_ids[] = (int) $menu_item->menu_item_parent;
       
   407 
   546 		// if the menu item corresponds to the currently-requested URL
   408 		// if the menu item corresponds to the currently-requested URL
   547 		} elseif ( 'custom' == $menu_item->object ) {
   409 		} elseif ( 'custom' == $menu_item->object && isset( $_SERVER['HTTP_HOST'] ) ) {
   548 			$_root_relative_current = untrailingslashit( $_SERVER['REQUEST_URI'] );
   410 			$_root_relative_current = untrailingslashit( $_SERVER['REQUEST_URI'] );
       
   411 
       
   412 			//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() ) {
       
   414 				$_root_relative_current = strtok( untrailingslashit( $_SERVER['REQUEST_URI'] ), '?' );
       
   415 			}
   549 			$current_url = set_url_scheme( 'http://' . $_SERVER['HTTP_HOST'] . $_root_relative_current );
   416 			$current_url = set_url_scheme( 'http://' . $_SERVER['HTTP_HOST'] . $_root_relative_current );
   550 			$raw_item_url = strpos( $menu_item->url, '#' ) ? substr( $menu_item->url, 0, strpos( $menu_item->url, '#' ) ) : $menu_item->url;
   417 			$raw_item_url = strpos( $menu_item->url, '#' ) ? substr( $menu_item->url, 0, strpos( $menu_item->url, '#' ) ) : $menu_item->url;
   551 			$item_url = untrailingslashit( $raw_item_url );
   418 			$item_url = set_url_scheme( untrailingslashit( $raw_item_url ) );
   552 			$_indexless_current = untrailingslashit( preg_replace( '/' . preg_quote( $wp_rewrite->index, '/' ) . '$/', '', $current_url ) );
   419 			$_indexless_current = untrailingslashit( preg_replace( '/' . preg_quote( $wp_rewrite->index, '/' ) . '$/', '', $current_url ) );
   553 
   420 
   554 			if ( $raw_item_url && in_array( $item_url, array( $current_url, $_indexless_current, $_root_relative_current ) ) ) {
   421 			if ( $raw_item_url && in_array( $item_url, array( $current_url, $_indexless_current, $_root_relative_current ) ) ) {
   555 				$classes[] = 'current-menu-item';
   422 				$classes[] = 'current-menu-item';
   556 				$menu_items[$key]->current = true;
   423 				$menu_items[$key]->current = true;
   649 /**
   516 /**
   650  * Retrieve the HTML list content for nav menu items.
   517  * Retrieve the HTML list content for nav menu items.
   651  *
   518  *
   652  * @uses Walker_Nav_Menu to create HTML list content.
   519  * @uses Walker_Nav_Menu to create HTML list content.
   653  * @since 3.0.0
   520  * @since 3.0.0
   654  * @see Walker::walk() for parameters and return description.
   521  *
       
   522  * @param array    $items The menu items, sorted by each menu item's menu order.
       
   523  * @param int      $depth Depth of the item in reference to parents.
       
   524  * @param stdClass $r     An object containing wp_nav_menu() arguments.
       
   525  * @return string The HTML list content for the menu items.
   655  */
   526  */
   656 function walk_nav_menu_tree( $items, $depth, $r ) {
   527 function walk_nav_menu_tree( $items, $depth, $r ) {
   657 	$walker = ( empty($r->walker) ) ? new Walker_Nav_Menu : $r->walker;
   528 	$walker = ( empty($r->walker) ) ? new Walker_Nav_Menu : $r->walker;
   658 	$args = array( $items, $depth, $r );
   529 	$args = array( $items, $depth, $r );
   659 
   530 
   660 	return call_user_func_array( array($walker, 'walk'), $args );
   531 	return call_user_func_array( array( $walker, 'walk' ), $args );
   661 }
   532 }
   662 
   533 
   663 /**
   534 /**
   664  * Prevents a menu item ID from being used more than once.
   535  * Prevents a menu item ID from being used more than once.
   665  *
   536  *
   666  * @since 3.0.1
   537  * @since 3.0.1
   667  * @access private
   538  * @access private
       
   539  *
       
   540  * @staticvar array $used_ids
       
   541  * @param string $id
       
   542  * @param object $item
       
   543  * @return string
   668  */
   544  */
   669 function _nav_menu_item_id_use_once( $id, $item ) {
   545 function _nav_menu_item_id_use_once( $id, $item ) {
   670 	static $_used_ids = array();
   546 	static $_used_ids = array();
   671 	if ( in_array( $item->ID, $_used_ids ) )
   547 	if ( in_array( $item->ID, $_used_ids ) ) {
   672 		return '';
   548 		return '';
       
   549 	}
   673 	$_used_ids[] = $item->ID;
   550 	$_used_ids[] = $item->ID;
   674 	return $id;
   551 	return $id;
   675 }
   552 }