WordPress.org

Make WordPress Core

Opened 9 months ago

Last modified 9 months ago

#40090 new defect (bug)

Walker::display_element does not populate $args[0]->has_children when it is cast as an Object

Reported by: JoelStransky Owned by:
Milestone: Awaiting Review Priority: normal
Severity: normal Version: 4.7.3
Component: Menus Keywords:
Focuses: Cc:

Description

When using the various hooks in Walker_Nav_Menu, the $args argument is expected to have a has_children object property.

Walker::display_element only creates and populates this property if $args[0] exists and is an array.

<?php
//display this element
$this->has_children = ! empty( $children_elements[ $id ] );
if ( isset( $args[0] ) && is_array( $args[0] ) ) {
        $args[0]['has_children'] = $this->has_children; // Back-compat.
}

But wp_nav_menu() casts $args as an object ensuring that this assignment will always fail.

Suggested Fix

Add an additional check for object type and assign appropriately.

<?php
//display this element
$this->has_children = ! empty( $children_elements[ $id ] );
if ( isset( $args[0] ) && is_array( $args[0] ) ) {
        $args[0]['has_children'] = $this->has_children; // Back-compat.
} else if ( isset( $args[0] ) && is_object( $args[0] ) ) {
        $args[0]->has_children = $this->has_children;
}

Change History (3)

#2 @JoelStransky
9 months ago

Here is a use case

<?php
add_filter( 'nav_menu_link_attributes', 'filter__nav_menu_link_attributes' , 10, 4 );
function filter__nav_menu_link_attributes ( $atts, $item, $args, $depth ) {
  if ( $args->has_children ) {  // PHP Notice:  Undefined property: stdClass::$has_children
    // modify $atts accordingly
  }
  return $atts;
}
Note: See TracTickets for help on using tickets.