0

I'm using the theme "Tesseract" as a parent theme, and I'd like to use the walker class to get menu descriptions. However, I am having trouble figuring out how to edit the php, because I don't know how to properly replace the parent theme's functions.

I need to change a parent theme's function

According to this page, I'm supposed to find is find the wp_nav_menu(), which they author suggests is most likely in header.php, and replace that function call with this.

<?php $walker = new Menu_With_Description; ?>

<?php wp_nav_menu( array( 'theme_location' => 'primary', 'menu_class' => 'nav-menu', 'walker' => $walker ) ); ?>

The problem is that for my theme, wp_nav_menu() is getting called in my the Parent Theme's functions.php file, not in header.php, although the containing function (tesseract_output_menu) is called inside of header.php. What this means that I am going to, most likely, have to replace a parent theme's function, but I'm not sure how to do that the right way.

tesseract_output_menu is that function inside the parent theme function.php file that is called inside of header.php, I am going to try to change it to a function called child_tesseract_output_menu.

This is the parent theme function:

function tesseract_output_menu( $cont, $contClass, $location, $depth ) {

    switch( $location ) :

        case 'primary': $hblox = 'header'; break;
        case 'primary_right': $hblox = 'header_right'; break;
        case 'secondary': $hblox = 'footer'; break;
        case 'secondary_right': $hblox = 'footer_right'; break;

    endswitch;

    $locs = get_theme_mod('nav_menu_locations');

    $menu = get_theme_mod('tesseract_' . $hblox . '_menu_select');

    $isMenu = get_terms( 'nav_menu' ) ? TRUE : FALSE;
    $locReserved = ( $locs[$location] ) ? TRUE : FALSE;
    $menuSelected = ( is_string($menu) ) ? TRUE : FALSE;

    // IF the location set as parameter has an associated menu, it's returned as a key-value pair in the $locs array - where the key is the location and the value is the menu ID. We need this latter to get the menu slug required later -in some cases- in the wp_nav_menu params array.
    if ( $locReserved ) {
        $menu_id = $locs[$location]; // $value = $array[$key]
        $menuObject = wp_get_nav_menu_object( $menu_id );
        $menu_slug = $menuObject->slug;
    };
    $custSet = ( $menuSelected && ( $menu !== 'none' ) );

    if ( empty( $isMenu ) ) : //Case 1 - IF THERE'S NO MENU CREATED -> easy scenario: no location setting, no customizer setting ( this latter only appears if there IS at least one menu created by the theme user ) => display basic menu

        wp_nav_menu( array(
            'theme_location' => 'primary',
            'menu_class' => 'nav-menu',
            'container_class' => '',
            'container' => FALSE,
            'depth' => $depth
            )
        );

    elseif ( !empty( $isMenu ) ) : //Case 2 - THERE'S AT LEAST ONE MENU CREATED

        if ( !$custSet && $locReserved ) { //no setting in customizer OR dropdown is set to blank value, location SET in Menus section => display menu associated with this location in Appearance ->
            wp_nav_menu( array(
               // 'menu' => $menuSlug,
                'menu' => $menu_slug, 
                'theme_location' => $location,
                'menu_class' => 'nav-menu',
                'container_class' => $contClass,
                'container' => $cont,
                'depth' => $depth
                )
            );

        } else if ( !$custSet && !$locReserved ) { //no setting in customizer OR dropdown is set to blank value, location NOT SET in Menus section => display basic menu

            wp_nav_menu( array(
                'theme_location' => 'primary',
                'menu_class' => 'nav-menu',
                'container_class' => '',
                'container' => FALSE,
                'depth' => $depth
                )
            );

        } else if ( $custSet ) { //menu set in customizer AND dropdown is NOT set to blank value, location SET OR NOT SET in Menus section => display menu set in customizer ( setting a menu to the given location in customizer will update any existing location-menu association in Appearance -> Menus, see function tesseract_set_menu_location() in functions.php )

            wp_nav_menu( array(
                'menu' => $menu,
                'theme_location' => $location,
                'menu_class' => 'nav-menu',
                'container_class' => $contClass,
                'container' => $cont,
                'depth' => $depth
                )
            );

        }

    endif;

}

Stack provides an example

From what I know I would probably want to use an action or filter to do this, as is demonstrated in this question: How to override parent functions in child themes?

The example isn't clear to me

The problem is that in example I'm trying to follow is not thoroughly explained and I don't quite understand how filters work yet. In that stack example, they seem to remove a function called twentyten_auto_excerpt_more, with one called osu_twentyten_auto_excerpt_more, but they do so using a first argument called excerpt_more:

The child override function in the Stack answer:

// Override read more link
function osu_twentyten_continue_reading_link() {
 return ' <a href="'. get_permalink() . '">' . __( 'Read on <span class="meta-nav">&rarr;</span>', 'twentyten-child' ) . '</a>';
}
function osu_twentyten_auto_excerpt_more( $more ) {
 return ' &hellip;' . osu_twentyten_continue_reading_link();
}
remove_filter( 'excerpt_more', 'twentyten_auto_excerpt_more' );
add_filter( 'excerpt_more', 'osu_twentyten_auto_excerpt_more' );

Since I want to change tesseract_output_menu, based on this example, I am pretty sure I would call my child function to replace the parent function tesseract_output_menu something like child_tesseract_output_menu,I think that is clear. But what I don't understand is what is the equivalent/analog of the first argument in my case, which is the same of exerpt_more in the above example. They don't say what excerpt_more is. I need to know what the first argument of the remove_filter andadd_filter` need to be in my case.

To make this clearer

Stack example

  1. functions used: add filter, remove filter
  2. second argument of remove filter (parent function to be replaced): twentyten_auto_excerpt_more
  3. second argument of add filter (child function): osu_twentyten_auto_excerpt_more
  4. first argument add filter and remove filter: exerpt more

My case, v1: replacing tesseract_output_menu:

  1. functions used: add filter, remove filter
  2. second argument of remove filter (parent function to be replaced): tesseract_output_menu
  3. second argument of add filter (child function) : child_tesseract_output_menu
  4. first argument add filter and remove filter: ??? What is the function I need to put in the first argument???

I realize that I might instead want to align things this way

My case, v2: replacing wp_nav_menu:

  1. functions used: add filter, remove filter
  2. second argument of remove filter (parent function to be replaced): wp_nav_menu
  3. second argument of add filter (child function) : child_wp_nav_menu
  4. first argument add filter and remove filter: tesseract_output_menu

What is the best approach to take, if i should use v1 of my case what is the equalivalent of excerpt_more in my case?

2 Answers 2

1

Go to your functions.php in your child theme add this:

function childtheme_override_tesseract_output_menu( $cont, $contClass, $location, $depth ) {
//tesseract_output_menu function code modified as you wish here    
}

In your parent theme functions.php, wrap the tesseract_output_menu function like this:

if (function_exists('childtheme_override_tesseract_output_menu')) {

    /**
     * run the child override
     */
    function tesseract_output_menu() {
        childtheme_override_tesseract_output_menu();
    }

} else {
   /**
    * run the original parent function
    */
   function tesseract_output_menu( $cont, $contClass, $location, $depth ) {
     //original code untouched   
   }
}

this way you can override the parent theme function, this is the standard way, i am not sure why the parent theme function its not already wrapped like that, you can see in the themes that come with wordpress the same code for it, so the function can be replaced if ( ! function_exists( 'twentysixteen_setup' ) ).

2
  • This is interesting. I'm glad you answered because it is teaching me, but at the same time I'm confused..is it not bad practice to edit the parent theme? I understand you included a catch so it doesn't crash if a different child theme is used, but still, this is how people recommend doing it? Feb 12, 2017 at 18:48
  • This is the standard for themes that are supposed to be parent i mean, a parent theme should give you a way to override his functions, yes its not recommended to edit a parent theme, but if its not offering you functions that can be overridden i am not sure if its a good parent theme.
    – David Lee
    Feb 12, 2017 at 19:44
0

I realized an easier approach that worked that involved editing my child's header.php file

  1. Inside child's header.php file find all calls to the wp_nav_menu containing function called tesseract_output_menu.
  2. Replace those of calls to tesseract_output_menu a to a new function called child_tesseract_output_menu.
  3. Include the desired edited version of that function in my child theme's functions.php file.

This is the walker class enabling function in my child theme's function.php file:

function child_tesseract_output_menu( $cont, $contClass, $location, $depth ) {

    switch( $location ) :

        case 'primary': $hblox = 'header'; break;
        case 'primary_right': $hblox = 'header_right'; break;
        case 'secondary': $hblox = 'footer'; break;
        case 'secondary_right': $hblox = 'footer_right'; break;

    endswitch;

    $locs = get_theme_mod('nav_menu_locations');

    $menu = get_theme_mod('tesseract_' . $hblox . '_menu_select');

    $isMenu = get_terms( 'nav_menu' ) ? TRUE : FALSE;
    $locReserved = ( $locs[$location] ) ? TRUE : FALSE;
    $menuSelected = ( is_string($menu) ) ? TRUE : FALSE;

    // IF the location set as parameter has an associated menu, it's returned as a key-value pair in the $locs array - where the key is the location and the value is the menu ID. We need this latter to get the menu slug required later -in some cases- in the wp_nav_menu params array.
    if ( $locReserved ) {
        $menu_id = $locs[$location]; // $value = $array[$key]
        $menuObject = wp_get_nav_menu_object( $menu_id );
        $menu_slug = $menuObject->slug;
    };
    $custSet = ( $menuSelected && ( $menu !== 'none' ) );

    if ( empty( $isMenu ) ) : //Case 1 - IF THERE'S NO MENU CREATED -> easy scenario: no location setting, no customizer setting ( this latter only appears if there IS at least one menu created by the theme user ) => display basic menu

       $walker = new Menu_With_Description; 

        wp_nav_menu( array(
            'theme_location' => 'primary',
            'menu_class' => 'nav-menu',
            'container_class' => '',
            'container' => FALSE,
            'depth' => $depth,
            'walker' => $walker
            )
        );

    elseif ( !empty( $isMenu ) ) : //Case 2 - THERE'S AT LEAST ONE MENU CREATED

        if ( !$custSet && $locReserved ) { //no setting in customizer OR dropdown is set to blank value, location SET in Menus section => display menu associated with this location in Appearance ->

$walker = new Menu_With_Description; 

 wp_nav_menu( array(
               // 'menu' => $menuSlug,
                'menu' => $menu_slug, 
                'theme_location' => $location,
                'menu_class' => 'nav-menu',
                'container_class' => $contClass,
                'container' => $cont,
                'depth' => $depth,
                'walker' => $walker
                )
            );

        } else if ( !$custSet && !$locReserved ) { //no setting in customizer OR dropdown is set to blank value, location NOT SET in Menus section => display basic menu
$walker = new Menu_With_Description; 


            wp_nav_menu( array(
                'theme_location' => 'primary',
                'menu_class' => 'nav-menu',
                'container_class' => '',
                'container' => FALSE,
                'depth' => $depth,
                'walker' => $walker
                )
            );

        } else if ( $custSet ) { //menu set in customizer AND dropdown is NOT set to blank value, location SET OR NOT SET in Menus section => display menu set in customizer ( setting a menu to the given location in customizer will update any existing location-menu association in Appearance -> Menus, see function tesseract_set_menu_location() in functions.php )

$walker = new Menu_With_Description; 

            wp_nav_menu( array(
                'menu' => $menu,
                'theme_location' => $location,
                'menu_class' => 'nav-menu',
                'container_class' => $contClass,
                'container' => $cont,
                'depth' => $depth,
                'walker' => $walker
                )
            );

        }

    endif;

}

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.