@@ -435,4 +435,72 @@ public function data_build_atts_should_build_attributes() {
435435 ),
436436 );
437437 }
438+
439+ /**
440+ * Tests that modifications to `$args` in the `nav_menu_item_args` filter do not leak between menu items.
441+ *
442+ * @ticket 37344
443+ *
444+ * @covers Walker_Nav_Menu::start_el
445+ */
446+ public function test_walker_nav_menu_start_el_should_not_leak_nav_menu_item_args_filter_changes_between_items () {
447+ add_filter ( 'nav_menu_item_args ' , array ( $ this , 'filter_nav_menu_item_args_append_marker ' ), 10 , 3 );
448+
449+ $ item1 = array (
450+ 'ID ' => 1 ,
451+ 'title ' => 'Item 1 ' ,
452+ 'classes ' => array (),
453+ 'current ' => false ,
454+ 'target ' => '' ,
455+ 'xfn ' => '' ,
456+ 'url ' => 'http://example.com/item1 ' ,
457+ );
458+
459+ $ item2 = array (
460+ 'ID ' => 2 ,
461+ 'title ' => 'Item 2 ' ,
462+ 'classes ' => array (),
463+ 'current ' => false ,
464+ 'target ' => '' ,
465+ 'xfn ' => '' ,
466+ 'url ' => 'http://example.com/item2 ' ,
467+ );
468+
469+ $ args = array (
470+ 'before ' => '' ,
471+ 'after ' => '' ,
472+ 'link_before ' => '' ,
473+ 'link_after ' => '' ,
474+ );
475+
476+ $ output1 = '' ;
477+ $ this ->walker ->start_el ( $ output1 , (object ) $ item1 , 0 , (object ) $ args );
478+
479+ $ output2 = '' ;
480+ $ this ->walker ->start_el ( $ output2 , (object ) $ item2 , 0 , (object ) $ args );
481+
482+ remove_filter ( 'nav_menu_item_args ' , array ( $ this , 'filter_nav_menu_item_args_append_marker ' ), 10 );
483+
484+ // Both menu items should have exactly one 'X' marker, not accumulating.
485+ $ this ->assertStringContainsString ( '>X<a href="http://example.com/item1">Item 1</a> ' , $ output1 );
486+ $ this ->assertStringContainsString ( '>X<a href="http://example.com/item2">Item 2</a> ' , $ output2 );
487+
488+ // Ensure no accumulation - Item 2 should not contain 'XX'.
489+ $ this ->assertStringNotContainsString ( '>XX<a href="http://example.com/item2">Item 2</a> ' , $ output2 );
490+ }
491+
492+ /**
493+ * Filter callback for testing nav_menu_item_args filter side effects.
494+ *
495+ * Appends a marker character to the 'before' argument to test for accumulation.
496+ *
497+ * @param stdClass $args An object of wp_nav_menu() arguments.
498+ * @param WP_Post $menu_item Menu item data object.
499+ * @param int $depth Depth of menu item. Used for padding.
500+ * @return stdClass Modified arguments object.
501+ */
502+ public function filter_nav_menu_item_args_append_marker ( $ args , $ menu_item , $ depth ) {
503+ $ args ->before .= 'X ' ;
504+ return $ args ;
505+ }
438506}
0 commit comments