WordPress.org

Make WordPress Core

Opened 3 years ago

Closed 2 years ago

Last modified 2 years ago

#37136 closed defect (bug) (duplicate)

'nav_menu_link_attributes' filter is called with $args as an object instead of an array

Reported by: Fab1en Owned by:
Milestone: Priority: normal
Severity: normal Version: 4.3.1
Component: Menus Keywords: dev-feedback
Focuses: docs, template Cc:
PR Number:

Description

When I register the nav_menu_link_attributes filter, the third argument $args is an object. But the documentation says it should be an array.

$atts - HTML attributes in an associative array
$item - Object containing item details. E.G: If the link is to a page $item will be a WP_Post object
$args - Array containing config with desired markup of nav item

You can see later on the same documentation page that $args is an object :

function add_specific_menu_location_atts( $atts, $item, $args ) {
    // check if the item is in the primary menu
    if( $args->theme_location == 'primary' ) {
      // add the desired attributes:
      $atts['class'] = 'menu-link-class';
    }
    return $atts;
}
add_filter( 'nav_menu_link_attributes', 'add_specific_menu_location_atts', 10, 3 );

Notice the $args->theme_location instead of $args['theme_location'].

That inconsistency would not bother me if I was not providing a fallback function for wp_nav_menu. In the fallback function, I call walk_page_tree, which in turn calls the nav_menu_link_attributes filter, but with $args set as an array.

wp_nav_menu( array( 
    'theme_location' => 'main',
    'fallback_cb' => 'my_default_menu'
) );

function my_default_menu( $args = array() ) {
    // get all published posts
    $list_args = $args;
    $list_args['echo'] = false;
    $list_args['walker'] = new Walker_Nav_Menu;
    $posts = get_posts( array( 'nopaging' => true ) );

    // generate menu HTML
    $menu = walk_page_tree( $posts, 0, 0, $list_args );
    if ( $args['echo'] ) echo $menu;
    else return $menu;
}

I cannot trace down where the array to object conversion is done.

Change History (7)

#1 @Fab1en
3 years ago

possibly related to #30109

#2 @ocean90
3 years ago

  • Focuses docs added
  • Version trunk deleted

walk_nav_menu_tree() expects an object while walk_page_tree() wants to have an array.

Function stack:

#1 wp_nav_menu( array(2) )	.../header.php:56
#2 walk_nav_menu_tree( array(3), long, object(stdClass)[89] )	.../nav-menu-template.php:183
#3 call_user_func_array( array(2), array(3) )	.../nav-menu-template.php:500
#4 Walker->walk( array(3), long, object(stdClass)[89] )	.../nav-menu-template.php:500
#5 Walker->display_element( object(WP_Post)[129], array(0), long, long, array(1), string(0) )	.../class-wp-walker.php:247
#6 call_user_func_array:( array(2), array(4) )	.../class-wp-walker.php:149
#7 Walker_Nav_Menu->start_el( string(0), object(WP_Post)[129], long, object(stdClass)[89], ??? )	.../class-wp-walker.php:149

An array to object conversion doesn't really happen but in step #6 the array with the WP_Term object gets merged with into another array: $cb_args = array_merge( array(&$output, $element, $depth), $args ); (WP_Walker::display_element()).

Looks like we need to improve the docs here.

Last edited 3 years ago by swissspidy (previous) (diff)

This ticket was mentioned in Slack in #docs by morganestes. View the logs.


3 years ago

#4 @milana_cap
2 years ago

  • Keywords dev-feedback added

Hi @Fab1en,

The documentation page you're referring to is deprecated. The new, updated and correct one is | here, where, as you have correctly noticed, it says that $args param is, in fact, an object of wp_nav_menu() arguments.

The codex.wordpress.org will be retired and replaced by developer.wordpress.org. Some pages (like this one) still exist on both places and some are already redirected to developer one. Please keep this in mind when you find some deprecated or incorrect information on codex. It is worth checking the data on the same page on developer. If data is incorrect there as well then, indeed, we have a bug in documentation.

I know this all is not quite clear from the message at the top of the page, but that message is suppose to inform visitors about codex being in process of retiring:

https://box.everhelper.me/attachment/995929/e9bf1cba-9f9c-4a50-bd91-d20dcaeb4186/654956-9Yh77OA9iEu2w1sw/screen.jpeg

#5 follow-up: @Fab1en
2 years ago

  • Version set to 4.3.1

Thanks @milana_cap for your answer.
The issue here is not really that the information is deprecated on the old codex documentation. The issue is that the filter is called inconsistently in two different situations : sometimes, the third argument is an object, and sometimes it's an array.

This issue was present in the version 4.3.1, so I should check if it's still present in 4.8.

#6 in reply to: ↑ 5 @SergeyBiryukov
2 years ago

  • Milestone Awaiting Review deleted
  • Resolution set to duplicate
  • Status changed from new to closed

Replying to Fab1en:

The issue is that the filter is called inconsistently in two different situations : sometimes, the third argument is an object, and sometimes it's an array.

Sounds like a duplicate of #24587.

#7 @SergeyBiryukov
2 years ago

Didn't mean to close the ticket right away, feel free to reopen if it's not a duplicate. Still seems like one though :)

Note: See TracTickets for help on using tickets.