class-walker-nav-menu.php 9.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279
  1. <?php
  2. /**
  3. * Nav Menu API: Walker_Nav_Menu class
  4. *
  5. * @package WordPress
  6. * @subpackage Nav_Menus
  7. * @since 4.6.0
  8. */
  9. /**
  10. * Core class used to implement an HTML list of nav menu items.
  11. *
  12. * @since 3.0.0
  13. *
  14. * @see Walker
  15. */
  16. class Walker_Nav_Menu extends Walker {
  17. /**
  18. * What the class handles.
  19. *
  20. * @since 3.0.0
  21. * @var string
  22. *
  23. * @see Walker::$tree_type
  24. */
  25. public $tree_type = array( 'post_type', 'taxonomy', 'custom' );
  26. /**
  27. * Database fields to use.
  28. *
  29. * @since 3.0.0
  30. * @todo Decouple this.
  31. * @var string[]
  32. *
  33. * @see Walker::$db_fields
  34. */
  35. public $db_fields = array(
  36. 'parent' => 'menu_item_parent',
  37. 'id' => 'db_id',
  38. );
  39. /**
  40. * Starts the list before the elements are added.
  41. *
  42. * @since 3.0.0
  43. *
  44. * @see Walker::start_lvl()
  45. *
  46. * @param string $output Used to append additional content (passed by reference).
  47. * @param int $depth Depth of menu item. Used for padding.
  48. * @param stdClass $args An object of wp_nav_menu() arguments.
  49. */
  50. public function start_lvl( &$output, $depth = 0, $args = null ) {
  51. if ( isset( $args->item_spacing ) && 'discard' === $args->item_spacing ) {
  52. $t = '';
  53. $n = '';
  54. } else {
  55. $t = "\t";
  56. $n = "\n";
  57. }
  58. $indent = str_repeat( $t, $depth );
  59. // Default class.
  60. $classes = array( 'sub-menu' );
  61. /**
  62. * Filters the CSS class(es) applied to a menu list element.
  63. *
  64. * @since 4.8.0
  65. *
  66. * @param string[] $classes Array of the CSS classes that are applied to the menu `<ul>` element.
  67. * @param stdClass $args An object of `wp_nav_menu()` arguments.
  68. * @param int $depth Depth of menu item. Used for padding.
  69. */
  70. $class_names = implode( ' ', apply_filters( 'nav_menu_submenu_css_class', $classes, $args, $depth ) );
  71. $class_names = $class_names ? ' class="' . esc_attr( $class_names ) . '"' : '';
  72. $output .= "{$n}{$indent}<ul$class_names>{$n}";
  73. }
  74. /**
  75. * Ends the list of after the elements are added.
  76. *
  77. * @since 3.0.0
  78. *
  79. * @see Walker::end_lvl()
  80. *
  81. * @param string $output Used to append additional content (passed by reference).
  82. * @param int $depth Depth of menu item. Used for padding.
  83. * @param stdClass $args An object of wp_nav_menu() arguments.
  84. */
  85. public function end_lvl( &$output, $depth = 0, $args = null ) {
  86. if ( isset( $args->item_spacing ) && 'discard' === $args->item_spacing ) {
  87. $t = '';
  88. $n = '';
  89. } else {
  90. $t = "\t";
  91. $n = "\n";
  92. }
  93. $indent = str_repeat( $t, $depth );
  94. $output .= "$indent</ul>{$n}";
  95. }
  96. /**
  97. * Starts the element output.
  98. *
  99. * @since 3.0.0
  100. * @since 4.4.0 The {@see 'nav_menu_item_args'} filter was added.
  101. * @since 5.9.0 Renamed `$item` to `$data_object` and `$id` to `$current_object_id`
  102. * to match parent class for PHP 8 named parameter support.
  103. *
  104. * @see Walker::start_el()
  105. *
  106. * @param string $output Used to append additional content (passed by reference).
  107. * @param WP_Post $data_object Menu item data object.
  108. * @param int $depth Depth of menu item. Used for padding.
  109. * @param stdClass $args An object of wp_nav_menu() arguments.
  110. * @param int $current_object_id Optional. ID of the current menu item. Default 0.
  111. */
  112. public function start_el( &$output, $data_object, $depth = 0, $args = null, $current_object_id = 0 ) {
  113. // Restores the more descriptive, specific name for use within this method.
  114. $menu_item = $data_object;
  115. if ( isset( $args->item_spacing ) && 'discard' === $args->item_spacing ) {
  116. $t = '';
  117. $n = '';
  118. } else {
  119. $t = "\t";
  120. $n = "\n";
  121. }
  122. $indent = ( $depth ) ? str_repeat( $t, $depth ) : '';
  123. $classes = empty( $menu_item->classes ) ? array() : (array) $menu_item->classes;
  124. $classes[] = 'menu-item-' . $menu_item->ID;
  125. /**
  126. * Filters the arguments for a single nav menu item.
  127. *
  128. * @since 4.4.0
  129. *
  130. * @param stdClass $args An object of wp_nav_menu() arguments.
  131. * @param WP_Post $menu_item Menu item data object.
  132. * @param int $depth Depth of menu item. Used for padding.
  133. */
  134. $args = apply_filters( 'nav_menu_item_args', $args, $menu_item, $depth );
  135. /**
  136. * Filters the CSS classes applied to a menu item's list item element.
  137. *
  138. * @since 3.0.0
  139. * @since 4.1.0 The `$depth` parameter was added.
  140. *
  141. * @param string[] $classes Array of the CSS classes that are applied to the menu item's `<li>` element.
  142. * @param WP_Post $menu_item The current menu item object.
  143. * @param stdClass $args An object of wp_nav_menu() arguments.
  144. * @param int $depth Depth of menu item. Used for padding.
  145. */
  146. $class_names = implode( ' ', apply_filters( 'nav_menu_css_class', array_filter( $classes ), $menu_item, $args, $depth ) );
  147. $class_names = $class_names ? ' class="' . esc_attr( $class_names ) . '"' : '';
  148. /**
  149. * Filters the ID attribute applied to a menu item's list item element.
  150. *
  151. * @since 3.0.1
  152. * @since 4.1.0 The `$depth` parameter was added.
  153. *
  154. * @param string $menu_item_id The ID attribute applied to the menu item's `<li>` element.
  155. * @param WP_Post $menu_item The current menu item.
  156. * @param stdClass $args An object of wp_nav_menu() arguments.
  157. * @param int $depth Depth of menu item. Used for padding.
  158. */
  159. $id = apply_filters( 'nav_menu_item_id', 'menu-item-' . $menu_item->ID, $menu_item, $args, $depth );
  160. $id = $id ? ' id="' . esc_attr( $id ) . '"' : '';
  161. $output .= $indent . '<li' . $id . $class_names . '>';
  162. $atts = array();
  163. $atts['title'] = ! empty( $menu_item->attr_title ) ? $menu_item->attr_title : '';
  164. $atts['target'] = ! empty( $menu_item->target ) ? $menu_item->target : '';
  165. if ( '_blank' === $menu_item->target && empty( $menu_item->xfn ) ) {
  166. $atts['rel'] = 'noopener';
  167. } else {
  168. $atts['rel'] = $menu_item->xfn;
  169. }
  170. $atts['href'] = ! empty( $menu_item->url ) ? $menu_item->url : '';
  171. $atts['aria-current'] = $menu_item->current ? 'page' : '';
  172. /**
  173. * Filters the HTML attributes applied to a menu item's anchor element.
  174. *
  175. * @since 3.6.0
  176. * @since 4.1.0 The `$depth` parameter was added.
  177. *
  178. * @param array $atts {
  179. * The HTML attributes applied to the menu item's `<a>` element, empty strings are ignored.
  180. *
  181. * @type string $title Title attribute.
  182. * @type string $target Target attribute.
  183. * @type string $rel The rel attribute.
  184. * @type string $href The href attribute.
  185. * @type string $aria-current The aria-current attribute.
  186. * }
  187. * @param WP_Post $menu_item The current menu item object.
  188. * @param stdClass $args An object of wp_nav_menu() arguments.
  189. * @param int $depth Depth of menu item. Used for padding.
  190. */
  191. $atts = apply_filters( 'nav_menu_link_attributes', $atts, $menu_item, $args, $depth );
  192. $attributes = '';
  193. foreach ( $atts as $attr => $value ) {
  194. if ( is_scalar( $value ) && '' !== $value && false !== $value ) {
  195. $value = ( 'href' === $attr ) ? esc_url( $value ) : esc_attr( $value );
  196. $attributes .= ' ' . $attr . '="' . $value . '"';
  197. }
  198. }
  199. /** This filter is documented in wp-includes/post-template.php */
  200. $title = apply_filters( 'the_title', $menu_item->title, $menu_item->ID );
  201. /**
  202. * Filters a menu item's title.
  203. *
  204. * @since 4.4.0
  205. *
  206. * @param string $title The menu item's title.
  207. * @param WP_Post $menu_item The current menu item object.
  208. * @param stdClass $args An object of wp_nav_menu() arguments.
  209. * @param int $depth Depth of menu item. Used for padding.
  210. */
  211. $title = apply_filters( 'nav_menu_item_title', $title, $menu_item, $args, $depth );
  212. $item_output = $args->before;
  213. $item_output .= '<a' . $attributes . '>';
  214. $item_output .= $args->link_before . $title . $args->link_after;
  215. $item_output .= '</a>';
  216. $item_output .= $args->after;
  217. /**
  218. * Filters a menu item's starting output.
  219. *
  220. * The menu item's starting output only includes `$args->before`, the opening `<a>`,
  221. * the menu item's title, the closing `</a>`, and `$args->after`. Currently, there is
  222. * no filter for modifying the opening and closing `<li>` for a menu item.
  223. *
  224. * @since 3.0.0
  225. *
  226. * @param string $item_output The menu item's starting HTML output.
  227. * @param WP_Post $menu_item Menu item data object.
  228. * @param int $depth Depth of menu item. Used for padding.
  229. * @param stdClass $args An object of wp_nav_menu() arguments.
  230. */
  231. $output .= apply_filters( 'walker_nav_menu_start_el', $item_output, $menu_item, $depth, $args );
  232. }
  233. /**
  234. * Ends the element output, if needed.
  235. *
  236. * @since 3.0.0
  237. * @since 5.9.0 Renamed `$item` to `$data_object` to match parent class for PHP 8 named parameter support.
  238. *
  239. * @see Walker::end_el()
  240. *
  241. * @param string $output Used to append additional content (passed by reference).
  242. * @param WP_Post $data_object Menu item data object. Not used.
  243. * @param int $depth Depth of page. Not Used.
  244. * @param stdClass $args An object of wp_nav_menu() arguments.
  245. */
  246. public function end_el( &$output, $data_object, $depth = 0, $args = null ) {
  247. if ( isset( $args->item_spacing ) && 'discard' === $args->item_spacing ) {
  248. $t = '';
  249. $n = '';
  250. } else {
  251. $t = "\t";
  252. $n = "\n";
  253. }
  254. $output .= "</li>{$n}";
  255. }
  256. }