: str_replace(): Passing null to parameter #2 ($replace) of type array|string is deprecated in
&& ! in_array( $ancestor_id, $active_ancestor_item_ids, true )
$active_ancestor_item_ids[] = $ancestor_id;
if ( in_array( home_url(), array( untrailingslashit( $current_url ), untrailingslashit( $_indexless_current ) ), true ) ) {
// Back compat for home link to match wp_page_menu().
$classes[] = 'current_page_item';
$active_parent_item_ids[] = (int) $menu_item->menu_item_parent;
$active_parent_object_ids[] = (int) $menu_item->post_parent;
$active_object = $menu_item->object;
// Give front page item the 'current-menu-item' class when extra query arguments are involved.
} elseif ( $item_url === $front_page_url && is_front_page() ) {
$classes[] = 'current-menu-item';
if ( untrailingslashit( $item_url ) === home_url() ) {
$classes[] = 'menu-item-home';
// Back-compat with wp_page_menu(): add "current_page_parent" to static home page link for any non-page query.
if ( ! empty( $home_page_id ) && 'post_type' === $menu_item->type
&& empty( $wp_query->is_page ) && $home_page_id === (int) $menu_item->object_id
$classes[] = 'current_page_parent';
$menu_items[ $key ]->classes = array_unique( $classes );
$active_ancestor_item_ids = array_filter( array_unique( $active_ancestor_item_ids ) );
$active_parent_item_ids = array_filter( array_unique( $active_parent_item_ids ) );
$active_parent_object_ids = array_filter( array_unique( $active_parent_object_ids ) );
foreach ( (array) $menu_items as $key => $parent_item ) {
$classes = (array) $parent_item->classes;
$menu_items[ $key ]->current_item_ancestor = false;
$menu_items[ $key ]->current_item_parent = false;
isset( $parent_item->type )
// Ancestral post object.
'post_type' === $parent_item->type
&& ! empty( $queried_object->post_type )
&& is_post_type_hierarchical( $queried_object->post_type )
&& in_array( (int) $parent_item->object_id, $queried_object->ancestors, true )
&& (int) $parent_item->object_id !== $queried_object->ID
'taxonomy' === $parent_item->type
&& isset( $possible_taxonomy_ancestors[ $parent_item->object ] )
&& in_array( (int) $parent_item->object_id, $possible_taxonomy_ancestors[ $parent_item->object ], true )
! isset( $queried_object->term_id ) ||
(int) $parent_item->object_id !== $queried_object->term_id
if ( ! empty( $queried_object->taxonomy ) ) {
$classes[] = 'current-' . $queried_object->taxonomy . '-ancestor';
$classes[] = 'current-' . $queried_object->post_type . '-ancestor';
if ( in_array( (int) $parent_item->db_id, $active_ancestor_item_ids, true ) ) {
$classes[] = 'current-menu-ancestor';
$menu_items[ $key ]->current_item_ancestor = true;
if ( in_array( (int) $parent_item->db_id, $active_parent_item_ids, true ) ) {
$classes[] = 'current-menu-parent';
$menu_items[ $key ]->current_item_parent = true;
if ( in_array( (int) $parent_item->object_id, $active_parent_object_ids, true ) ) {
$classes[] = 'current-' . $active_object . '-parent';
if ( 'post_type' === $parent_item->type && 'page' === $parent_item->object ) {
// Back compat classes for pages to match wp_page_menu().
if ( in_array( 'current-menu-parent', $classes, true ) ) {
$classes[] = 'current_page_parent';
if ( in_array( 'current-menu-ancestor', $classes, true ) ) {
$classes[] = 'current_page_ancestor';
$menu_items[ $key ]->classes = array_unique( $classes );
* Retrieves the HTML list content for nav menu items.
* @uses Walker_Nav_Menu to create HTML list content.
* @param array $items The menu items, sorted by each menu item's menu order.
* @param int $depth Depth of the item in reference to parents.
* @param stdClass $args An object containing wp_nav_menu() arguments.
* @return string The HTML list content for the menu items.
function walk_nav_menu_tree( $items, $depth, $args ) {
$walker = ( empty( $args->walker ) ) ? new Walker_Nav_Menu() : $args->walker;
return $walker->walk( $items, $depth, $args );
* Prevents a menu item ID from being used more than once.
function _nav_menu_item_id_use_once( $id, $item ) {
static $_used_ids = array();
if ( in_array( $item->ID, $_used_ids, true ) ) {
$_used_ids[] = $item->ID;
* Remove the `menu-item-has-children` class from bottom level menu items.
* This runs on the {@see 'nav_menu_css_class'} filter. The $args and $depth
* parameters were added after the filter was originally introduced in
* WordPress 3.0.0 so this needs to allow for cases in which the filter is
* @see https://core.trac.wordpress.org/ticket/56926
* @param string[] $classes Array of the CSS classes that are applied to the menu item's `<li>` element.
* @param WP_Post $menu_item The current menu item object.
* @param stdClass|false $args An object of wp_nav_menu() arguments. Default false ($args unspecified when filter is called).
* @param int|false $depth Depth of menu item. Default false ($depth unspecified when filter is called).
* @return string[] Modified nav menu classes.
function wp_nav_menu_remove_menu_item_has_children_class( $classes, $menu_item, $args = false, $depth = false ) {
* Account for the filter being called without the $args or $depth parameters.
* This occurs when a theme uses a custom walker calling the `nav_menu_css_class`
* filter using the legacy formats prior to the introduction of the $args and
* As both of these parameters are required for this function to determine
* both the current and maximum depth of the menu tree, the function does not
* attempt to remove the `menu-item-has-children` class if these parameters
if ( false === $depth || false === $args ) {
$max_depth = isset( $args->depth ) ? (int) $args->depth : 0;
// Depth is 0-based so needs to be increased by one.
// Complete menu tree is displayed.
if ( 0 === $max_depth ) {
* Remove the `menu-item-has-children` class from bottom level menu items.
* -1 is used to display all menu items in one level so the class should
* be removed from all menu items.
if ( -1 === $max_depth || $depth >= $max_depth ) {
$classes = array_diff( $classes, array( 'menu-item-has-children' ) );