1

After adding wp-custom-menu-filter plugin - to hide some menu items for not-logged in users, the current_page_item class disappeared from my menu. $item->classes in the walker is an empty array, instead of usual page-item-$id, current_page_item.

I've looked at the source, but it does not modify the classes array, so I don't know what's going on. Here is the relevant part of the code.

function wps_custom_nav_menu_items( $args ){
    global $wpcmfp_settings;

    $nav_item_db_id = $args[1]->ID;
    $nav_menu = wp_get_object_terms( $nav_item_db_id, 'nav_menu' );
    $menu_id = $nav_menu[0]->term_id;

    // Get the class to exclude
    if ( !is_user_logged_in() ) {
        $exclusion_class = $wpcmfp_settings[ 'menu-' . $menu_id . '-loggedout' ];
    }
    else {
        $exclusion_class = $wpcmfp_settings[ 'menu-' . $menu_id . '-loggedin' ];
    }

    $nav_items = wp_get_nav_menu_items( $menu_id );

    // Cycle through all nav_items
    foreach ( $nav_items as $nav_item ) {   

        // Cycle through all classes
        for ( $i=0; $i < count( $nav_item->classes ); $i++ ) {
            $exclude = false;

            // if nothing is there set to add
            if ( strlen ( $nav_item->classes[ $i ] ) < 1 ) {
                $exclude = false;
            }
            else
            {   
                // if matches add to exclusion array & break loop
                if ( $nav_item->classes[ $i ] == $exclusion_class ) {
                    $excluded_nav_items[] = $nav_item; 
                    $exclude = true;
                    break;
                }
            }
        }

        if ( $exclude != true )
            $modified_nav_items[] = $nav_item;

    }

    return $modified_nav_items;
}

add_filter( 'wp_nav_menu_objects', 'wps_custom_nav_menu_items' , 10 , 3);

I'm using custom page walker, I've tried using the default one with no effect, and the custom one works just fine without this plugin. Here is the code of the walker:

class My_Walker_Page extends Walker_Nav_Menu {

  protected $_counter = 0;
  protected $_itemsPerColumn = 1;

  function start_lvl(&$output, $depth) {
    $this->_counter = 0;

    $output .= '<some html>';

  }

  function end_lvl(&$output, $depth) {
    $output .= '<some html>';        
    $this->_counter = 0;
  }

  function start_el(&$output, $page, $depth, $args, $current_page = null) {

    $args = ( array ) $args;

    if ($depth == 0) {
      return parent::start_el ( $output, $page, $depth, $args, $current_page );
    }

    if ($depth == 1) {
      extract ( $args, EXTR_SKIP );
      $output .= '<dt><a href="' . esc_attr ( $page->url ) . '" title="' . esc_attr ( wp_strip_all_tags ( apply_filters ( 'the_title', $page->title, $page->ID ) ) ) . '">' . $link_before . apply_filters ( 'the_title', $page->title, $page->ID ) . $link_after . '</a>';

      if (! empty ( $page->description )) {
        $output .= '<span class="menu_item_description">' . $page->description . '</span>';
      }

      $output .= '</dt>';

      $this->_counter ++;
      if ($this->_counter % $this->_itemsPerColumn == 0) {
        $output .= '</dl><dl>';
      }

    }
  }

  function end_el(&$output, $page, $depth) {
    if ($depth == 0) {
      return parent::end_el ( &$output, $page, $depth );
    }
  }

  function display_element($element, &$children_elements, $max_depth, $depth = 0, $args, &$output) {

    if (! $element)
      return;

    $id_field = $this->db_fields ['id'];
    if ($depth == 0) {
      $this->_itemsPerColumn = ceil ( count ( $children_elements [$element->$id_field] ) / 4 );
    }

    return parent::display_element ( $element, $children_elements, $max_depth, $depth, $args, $output );
  }
}

I'm OK with going with another way to hide menu items for non-logged in users, instead of fixing the plugin, but since I've never used the wp_nav_menu_objects I really don't know what is going on.

1 Answer 1

0

After few hours of debugging I found out, that the wps_custom_nav_menu_items() actually receives the nav_menu_items with classes, applied by the _wp_menu_item_classes_by_context, but instead of using them, it reloads the entire menu from the database! So if you change

$nav_items = wp_get_nav_menu_items( $menu_id );

To

$nav_items = $args;

(or just remove the line and rename the function argument), it works as expected.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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