@@ -73,9 +73,27 @@ public function start_lvl( &$output, $depth = 0, $args = null ) {
7373 * @param int $depth Depth of menu item. Used for padding.
7474 */
7575 $ class_names = implode ( ' ' , apply_filters ( 'nav_menu_submenu_css_class ' , $ classes , $ args , $ depth ) );
76- $ class_names = $ class_names ? ' class=" ' . esc_attr ( $ class_names ) . '" ' : '' ;
7776
78- $ output .= "{$ n }{$ indent }<ul $ class_names> {$ n }" ;
77+ $ atts = array ();
78+ $ atts ['class ' ] = ! empty ( $ class_names ) ? $ class_names : '' ;
79+
80+ /**
81+ * Filters the HTML attributes applied to a menu list element.
82+ *
83+ * @since 6.3.0
84+ *
85+ * @param array $atts {
86+ * The HTML attributes applied to the `<ul>` element, empty strings are ignored.
87+ *
88+ * @type string $class HTML CSS class attribute.
89+ * }
90+ * @param stdClass $args An object of `wp_nav_menu()` arguments.
91+ * @param int $depth Depth of menu item. Used for padding.
92+ */
93+ $ atts = apply_filters ( 'nav_menu_submenu_attributes ' , $ atts , $ args , $ depth );
94+ $ attributes = $ this ->build_atts ( $ atts );
95+
96+ $ output .= "{$ n }{$ indent }<ul {$ attributes }> {$ n }" ;
7997 }
8098
8199 /**
@@ -156,7 +174,6 @@ public function start_el( &$output, $data_object, $depth = 0, $args = null, $cur
156174 * @param int $depth Depth of menu item. Used for padding.
157175 */
158176 $ class_names = implode ( ' ' , apply_filters ( 'nav_menu_css_class ' , array_filter ( $ classes ), $ menu_item , $ args , $ depth ) );
159- $ class_names = $ class_names ? ' class=" ' . esc_attr ( $ class_names ) . '" ' : '' ;
160177
161178 /**
162179 * Filters the ID attribute applied to a menu item's list item element.
@@ -170,9 +187,30 @@ public function start_el( &$output, $data_object, $depth = 0, $args = null, $cur
170187 * @param int $depth Depth of menu item. Used for padding.
171188 */
172189 $ id = apply_filters ( 'nav_menu_item_id ' , 'menu-item- ' . $ menu_item ->ID , $ menu_item , $ args , $ depth );
173- $ id = $ id ? ' id=" ' . esc_attr ( $ id ) . '" ' : '' ;
174190
175- $ output .= $ indent . '<li ' . $ id . $ class_names . '> ' ;
191+ $ li_atts = array ();
192+ $ li_atts ['id ' ] = ! empty ( $ id ) ? $ id : '' ;
193+ $ li_atts ['class ' ] = ! empty ( $ class_names ) ? $ class_names : '' ;
194+
195+ /**
196+ * Filters the HTML attributes applied to a menu's list item element.
197+ *
198+ * @since 6.3.0
199+ *
200+ * @param array $li_atts {
201+ * The HTML attributes applied to the menu item's `<li>` element, empty strings are ignored.
202+ *
203+ * @type string $class HTML CSS class attribute.
204+ * @type string $id HTML id attribute.
205+ * }
206+ * @param WP_Post $menu_item The current menu item object.
207+ * @param stdClass $args An object of wp_nav_menu() arguments.
208+ * @param int $depth Depth of menu item. Used for padding.
209+ */
210+ $ li_atts = apply_filters ( 'nav_menu_item_attributes ' , $ li_atts , $ menu_item , $ args , $ depth );
211+ $ li_attributes = $ this ->build_atts ( $ li_atts );
212+
213+ $ output .= $ indent . '<li ' . $ li_attributes . '> ' ;
176214
177215 $ atts = array ();
178216 $ atts ['title ' ] = ! empty ( $ menu_item ->attr_title ) ? $ menu_item ->attr_title : '' ;
@@ -214,15 +252,8 @@ public function start_el( &$output, $data_object, $depth = 0, $args = null, $cur
214252 * @param stdClass $args An object of wp_nav_menu() arguments.
215253 * @param int $depth Depth of menu item. Used for padding.
216254 */
217- $ atts = apply_filters ( 'nav_menu_link_attributes ' , $ atts , $ menu_item , $ args , $ depth );
218-
219- $ attributes = '' ;
220- foreach ( $ atts as $ attr => $ value ) {
221- if ( is_scalar ( $ value ) && '' !== $ value && false !== $ value ) {
222- $ value = ( 'href ' === $ attr ) ? esc_url ( $ value ) : esc_attr ( $ value );
223- $ attributes .= ' ' . $ attr . '=" ' . $ value . '" ' ;
224- }
225- }
255+ $ atts = apply_filters ( 'nav_menu_link_attributes ' , $ atts , $ menu_item , $ args , $ depth );
256+ $ attributes = $ this ->build_atts ( $ atts );
226257
227258 /** This filter is documented in wp-includes/post-template.php */
228259 $ title = apply_filters ( 'the_title ' , $ menu_item ->title , $ menu_item ->ID );
@@ -286,4 +317,23 @@ public function end_el( &$output, $data_object, $depth = 0, $args = null ) {
286317 $ output .= "</li> {$ n }" ;
287318 }
288319
320+ /**
321+ * Builds a string of HTML attributes from an array of key/value pairs.
322+ * Empty values are ignored.
323+ *
324+ * @since 6.3.0
325+ *
326+ * @param array $atts Optional. An array of HTML attribute key/value pairs. Default empty array.
327+ * @return string A string of HTML attributes.
328+ */
329+ protected function build_atts ( $ atts = array () ) {
330+ $ attribute_string = '' ;
331+ foreach ( $ atts as $ attr => $ value ) {
332+ if ( false !== $ value && '' !== $ value && is_scalar ( $ value ) ) {
333+ $ value = ( 'href ' === $ attr ) ? esc_url ( $ value ) : esc_attr ( $ value );
334+ $ attribute_string .= ' ' . $ attr . '=" ' . $ value . '" ' ;
335+ }
336+ }
337+ return $ attribute_string ;
338+ }
289339}
0 commit comments