Creating new menu item – WordPress

I’m looking for a way to create a new item that can be added to a menu.

Here are the details of my problem: I use WPML. WPML have that nice feature that you can add the switcher to a menu, automatically. It adds it at the end of the menu, no control on that.

Read More

Thing is, I want my language switcher to be element 4 out of 6. That feature to automatically add the element at the end doesn’t fit my needs.

So I want to create a new element that can be used in apparence->menu to put my language switcher exactly at the spot I want it.

Is there any way to do that?

TLDR: I want to be able to push custom HTML/PHP code in a menu element (Apparence->Menu). Any functions to do so?

Related posts

3 comments

  1. From wp-includes/nav-menu-template.php, in Walker_Nav_Menu::start_el:

    /**
     * Filter a menu item's starting output.
     *
     * The menu item's starting output only includes `$args->before`, the opening `<a>`,
     * the menu item's title, the closing `</a>`, and `$args->after`. Currently, there is
     * no filter for modifying the opening and closing `<li>` for a menu item.
     *
     * @since 3.0.0
     *
     * @param string $item_output The menu item's starting HTML output.
     * @param object $item        Menu item data object.
     * @param int    $depth       Depth of menu item. Used for padding.
     * @param array  $args        An array of {@see wp_nav_menu()} arguments.
     */
    $output .= apply_filters( 'walker_nav_menu_start_el', $item_output, $item, $depth, $args );
    

    Which means you can append to individual nav menu item HTML contents (right before the last li tag) using that filter. $item_output contains the HTML generated for the item so far. Example:

    <?php
    
    add_filter('walker_nav_menu_start_el', function ($item_output) {
        return $item_output . '<span>hello world</span>';
    });
    

    That would append <span>hello world</span> to each nav menu item HTML. A closing li tag will be appended after this filter. You can use the 4th argument ($args) to validate the currently rendering navigation menu.

  2. All right, I have temporary solution.

    These are steps:

    1. Open wp-contentpluginssitepress-multilingual-cmsinclanguage-switcher.php
    2. Go somewhere around line 786, where is function wp_nav_menu_items_filter($items, $args){
    3. Add this right after first {:

      $tempitems = $items;  
      $tempitemsexplode = explode("n", $tempitems);  
      $items = "";  
      $id = 2; //This is where widget will be located: example, if you want it to be at place 4, write 5
      
    4. Right before if ( $abs_menu_id == $settings_menu_id || false === $abs_menu_id ) { add this:

      $id = 2;  
      for ($i = 0; $i < $id; $i++){  
          $items .= $tempitemsexplode[$i];  
      }  
      for($i = 0; $i < count($tempitemsexplode); $i++){  
          If ($i == $id){  
      
    5. Go to bottom of function and before:
      }
      return $items;
      Add: }}

    6. Now, before return $items; Add:

      for ($i = $id; $i < count($tempitemsexplode); $i++){  
          $items .= $tempitemsexplode[$i];  
      }
      

    If you get stuck here is how that whole function looks for me:

    function wp_nav_menu_items_filter($items, $args){
        $tempitems = $items;
        $tempitemsexplode = explode("n", $tempitems);
        $items = "";
        global $sitepress_settings, $sitepress;
    
        $current_language = $sitepress->get_current_language();
        $default_language = $sitepress->get_default_language();
        // menu can be passed as integer or object
        if(isset($args->menu->term_id)) $args->menu = $args->menu->term_id;
    
        $abs_menu_id = icl_object_id($args->menu, 'nav_menu', false, $default_language );
        $settings_menu_id = icl_object_id( $sitepress_settings[ 'menu_for_ls' ], 'nav_menu', false, $default_language );
    
        $id = 2;
        for ($i = 0; $i < $id; $i++){
            $items .= $tempitemsexplode[$i];
        }
    
        for($i = 0; $i < count($tempitemsexplode); $i++){
            If ($i == $id){
                if ( $abs_menu_id == $settings_menu_id  || false === $abs_menu_id ) {
    
                    $languages = $sitepress->get_ls_languages();
    
    
                    $items .= '<li class="menu-item menu-item-language menu-item-language-current">';
                    if(isset($args->before)){
                        $items .= $args->before;
                    }
                    $items .= '<a href="#" onclick="return false">';
                    if(isset($args->link_before)){
                        $items .= $args->link_before;
                    }
    
                    $language_name = '';
                    if ( $sitepress_settings[ 'icl_lso_native_lang' ] ) {
                        $language_name .= $languages[ $current_language ][ 'native_name' ];
                    }
                    if ( $sitepress_settings[ 'icl_lso_display_lang' ] && $sitepress_settings[ 'icl_lso_native_lang' ] ) {
                        $language_name .= ' (';
                    }
                    if ( $sitepress_settings[ 'icl_lso_display_lang' ] ) {
                        $language_name .= $languages[ $current_language ][ 'translated_name' ];
                    }
                    if ( $sitepress_settings[ 'icl_lso_display_lang' ] && $sitepress_settings[ 'icl_lso_native_lang' ] ) {
                        $language_name .= ')';
                    }
    
    
    
                    $alt_title_lang = esc_attr($language_name);
    
                    if( $sitepress_settings['icl_lso_flags'] ){
                        $items .= '<img class="iclflag" src="' . $languages[ $current_language ][ 'country_flag_url' ] . '" width="18" height="12" alt="' . $alt_title_lang . '" title="' . esc_attr( $language_name ) . '" />';
                    }
    
                    $items .= $language_name;
    
                    if(isset($args->link_after)){
                        $items .= $args->link_after;
                    }
                    $items .= '</a>';
                    if(isset($args->after)){
                        $items .= $args->after;
                    }
    
                    unset($languages[ $current_language ]);
                    $sub_items = false;
                    $menu_is_vertical = !isset($sitepress_settings['icl_lang_sel_orientation']) || $sitepress_settings['icl_lang_sel_orientation'] == 'vertical';
                    if(!empty($languages)){
                        foreach($languages as $lang){
                            $sub_items .= '<li class="menu-item menu-item-language menu-item-language-current">';
                            $sub_items .= '<a href="'.$lang['url'].'">';
    
                            $language_name = '';
                            if ( $sitepress_settings[ 'icl_lso_native_lang' ] ) {
                                $language_name .= $lang[ 'native_name' ];
                            }
                            if ( $sitepress_settings[ 'icl_lso_display_lang' ] && $sitepress_settings[ 'icl_lso_native_lang' ] ) {
                                $language_name .= ' (';
                            }
                            if ( $sitepress_settings[ 'icl_lso_display_lang' ] ) {
                                $language_name .= $lang[ 'translated_name' ];
                            }
                            if ( $sitepress_settings[ 'icl_lso_display_lang' ] && $sitepress_settings[ 'icl_lso_native_lang' ] ) {
                                $language_name .= ')';
                            }
                            $alt_title_lang = esc_attr($language_name);
    
                            if( $sitepress_settings['icl_lso_flags'] ){
                                $sub_items .= '<img class="iclflag" src="'.$lang['country_flag_url'].'" width="18" height="12" alt="'.$alt_title_lang.'" title="' . $alt_title_lang . '" />';
                            }
                            $sub_items .= $language_name;
    
                            $sub_items .= '</a>';
                            $sub_items .= '</li>';
    
                        }
                        if( $sub_items && $menu_is_vertical ) {
                            $sub_items = '<ul class="sub-menu submenu-languages">' . $sub_items . '</ul>';
                        }
                    }
    
                    if( $menu_is_vertical ) {
                        $items .= $sub_items;
                        $items .= '</li>';
                    } else {
                        $items .= '</li>';
                        $items .= $sub_items;
                    }
                }
            }
        }
    
        for ($i = $id; $i < count($tempitemsexplode); $i++){
            $items .= $tempitemsexplode[$i];
        }
    
        return $items;
    
    }
    

    I will try to make it easier to change where you want to place widget.
    Comment if you have problems. Good luck!

    Edit: Explanation what this modified function does.
    This function is used to add language switcher to menu.
    When this function is called, we have $items string containing all menu items.
    I transferred all menu items from $items to $tempitems and set $items to empty string.
    Why? Because now we can insert widget as first menu item or between some menu items.

    Then we explode that $tempitems string so we could use another order.

    When you now specify $id this becomes our offset.

    And now in first loop, with help of $id, we add some temp items to empty $items string, and then language widget and at the end remaining menu items.

  3. You can create a new template even if you’re using a pre-developed theme or template.

    Just copy the code from the template you want to use and modify it accordingly on your localhost and upload the modified copy to the theme directory.

    Make sure you keep a copy in case you update the theme to a newer version because it’ll be overwritten.

    Another option would be to develop a child theme.

Comments are closed.