14

I've looked for plugins and couldn't find anything and I believe this should be a core feature.

The Problem:

The current methodology for replacing a custom link, or any menu link is by doing the following process:

  1. Remove old menu link
  2. Insert new link
  3. Drag new link from end of list
  4. Drop new link in desired location
  5. repeat steps 3 and 4 until you hit the jackpot
  6. Enter menu options again (css, label etc)

Why is it a problem

It is very inefficient, especially when: (a) dealing with huge menus (b) menus with many sublevels (c) replacing many menu items which have custom options

Solution requirements

  1. Retains Menu position / hierarchy
  2. Retains Options (css class, label, title)
  3. Choose from Pages / Posts / Categories etc

Demonstration

http://puu.sh/laSEi/81b0d41705.png

Should be that simple:

enter image description here

Other possible ideas are duplicating / "add child link to this"/ or even adding new links to top of list instead of bottom.

Any feedback appreciated.

  • 4
    +1 for a well formulated question - I agree with you, it's not very efficient. – birgire Nov 9 '15 at 10:55
  • 3
    The problem with this question is that I don't see any simple solution to the problem that can fit the format here. There probably a need to make some functionality adjustments in several areas. I suggest to open a ticket for it in trac as it sounds like a worthy feature request. – Mark Kaplun Nov 9 '15 at 13:50
  • 1
    Maybe you can add the search from the TinyMCE to find the posts, pages in the URL field, script wplink.js – bueltge Nov 9 '15 at 21:04
  • 1
    @MarkKaplun I thought someone might know a unpopular or otherwise private plugin for it, anyway, I followed your suggestion and created a trac request @ core.trac.wordpress.org/ticket/34648 what is the appropiate way to end this question on stackexchange? – Aziz Nov 10 '15 at 17:16
  • 2
    don't end it, not all questions have an acceptable or even valid answer. Some times it is good to know that other people also were looking at the same issue and didn't find an answer, sometimes someone does make a very late answer – Mark Kaplun Nov 10 '15 at 17:20
1

Although this does not directly answer the question, the code on which it is based provides the functionality. The code set is:

function install_menus() {
    require_once dirname( __FILE__) . '/data.php';
    $menus = get_menus_data();
    if ( ! empty ( $menus ) ) foreach ( $menus as $menu ) {
        if ( $menu['build'] ) {
            $menu_id = create_nav_menu( $menu );
            add_items_to_menu( $menu_id, $menu['slug'], $menu['items'] );
        }
    }
}

function create_nav_menu( $menu ) {
    if ( $exists = wp_get_nav_menu_object( $menu['name'] ) ) {
        $menu_id = $exists -> term_id;
          if ( empty ( $menu_id ) ) {
            $menu_id = wp_create_nav_menu( $menu['name'] );
        } 
    }
    else {
        $menu_id = wp_create_nav_menu( $menu['name'] );
    }
    return $menu_id;
}
function add_items_to_menu( $menu_id, $slug, $items ) {
    if ( $items ) foreach ( $items as $item ) {
        if ( $item['build'] ) {
            $slug = ( $item['title'] == 'Home' ) ? 'home' : $item['slug'];
            if ( ! menu_item_exists( $slug, $menu_id ) ) {
                wp_update_nav_menu_item( $menu_id, 0, array (
                    'menu-item-title' =>  __( $item['title'] ),
                    'menu-item-classes' => '',
                    'menu-item-url' => home_url( $item['slug'] . '/' ), 
                    'menu-item-status' => 'publish'
                    ) );
            }
        }
    }
}
function menu_item_exists( $slug, $menu_id ) {
    $args = array(
        'order'                  => 'ASC',
        'orderby'                => 'menu_order',
        'post_type'              => 'nav_menu_item',
        'post_status'            => 'publish',
        'output'                 => ARRAY_A,
        'output_key'             => 'menu_order',
        'nopaging'               => true,
        'update_post_term_cache' => false ); 

    $existing = wp_get_nav_menu_items( $menu_id, $args );
    $found = false;
    foreach ( $existing as $exists ) {
        if( strpos( $exists->post_name, $slug ) !== FALSE  ) {  //pretty good search (not exact).
            $found = true;
            break;
        }

    }
    return $found;
}

and the data file is:

function get_menus_data() {
    $items = array ( 
        array ( 
            'name' => 'Main Menu', 'slug' => 'main-menu', 'build' => 1, 
            'items' => array (
                array ( 'title' => 'Home', 'slug' => '', 'build' => 1 ), //slug should be empty
                array ( 'title' => 'Blog', 'slug' => 'blog', 'build' => 1 ),
                array ( 'title' => 'About', 'slug' => 'about', 'build' => 1 ),
                array ( 'title' => 'Contact', 'slug' => 'contact', 'build' => 1 ),
                ),
        ),
        array ( 
            'name' => 'Secondary Menu', 'slug' => 'secondary-menu', 'build' => 0,
            'items' => array (
                array ( 'title' => 'Home', 'slug' => '', 'build' => 1 ),
                array ( 'title' => 'Blog', 'slug' => 'blog', 'build' => 1 ),
                array ( 'title' => 'About', 'slug' => 'about', 'build' => 1 ),
                array ( 'title' => 'Contact', 'slug' => 'contact', 'build' => 1 ),
                ),
        ),
        array ( 
            'name' => 'Footer Menu', 'slug' => 'footer-menu', 'build' => 1,
            'items' => array (
                array ( 'title' => 'Terms', 'slug' => 'terms', 'build' => 1 ),
                array ( 'title' => 'Privacy', 'slug' => 'privacy', 'build' => 1 ),
                array ( 'title' => 'Contact', 'slug' => 'contact', 'build' => 1 ),
                ),
            ) 
    );
    return $items;
}

An interface would need to be built on top of this to allow for the selection that is asked, but this code is working and tested.

  • Hello, thank you for your answer. Could you please elaborate and explain the code you posted? – Aziz Nov 17 '15 at 21:34
  • If you copy and past the code into a plugin or a theme's functions.php it should create the menu items contained within the get_menus_data() function. In order to have a search result dynamically populate a menu item, functions are needed which use the WordPress API to do that. These functions are part of a complete self installing package by which menu items can be configured in advance, ideally eliminating the need to do this after the fact. Since these functions provide the "behind the scenes work" they could be used as a basis for the search functionality you are after. – cbos Nov 18 '15 at 20:33
1

I'm not sure this is an answer, but more a discussion point.

Has anyone ever considered Advanced Custom Fields for building WP menus? I've done this a couple of times, and it allows me to build out a custom structure along with custom menu-item attributes and build out the HTML for the menu without a complicated walker that would be needed with default WP menus.

enter image description here

ACF

if( function_exists('acf_add_local_field_group') ):

acf_add_local_field_group(array (
    'key' => 'group_56532ec144a4b',
    'title' => 'Menu',
    'fields' => array (
        array (
            'key' => 'field_5653338918f43',
            'label' => 'Menus',
            'name' => 'menus',
            'type' => 'flexible_content',
            'instructions' => '',
            'required' => 0,
            'conditional_logic' => 0,
            'wrapper' => array (
                'width' => '',
                'class' => '',
                'id' => '',
            ),
            'button_label' => 'Add Menu',
            'min' => '',
            'max' => '',
            'layouts' => array (
                array (
                    'key' => '56533396b10bc',
                    'name' => 'menu',
                    'label' => 'Menu',
                    'display' => 'block',
                    'sub_fields' => array (
                        array (
                            'key' => 'field_56533fc6f25e7',
                            'label' => 'Menu Name',
                            'name' => 'menu__name',
                            'type' => 'text',
                            'instructions' => '',
                            'required' => 0,
                            'conditional_logic' => 0,
                            'wrapper' => array (
                                'width' => '',
                                'class' => '',
                                'id' => '',
                            ),
                            'default_value' => '',
                            'placeholder' => '',
                            'prepend' => '',
                            'append' => '',
                            'maxlength' => '',
                            'readonly' => 0,
                            'disabled' => 0,
                        ),
                        array (
                            'key' => 'field_56532ec718f40',
                            'label' => 'Menu Items',
                            'name' => 'menu__items',
                            'type' => 'flexible_content',
                            'instructions' => '',
                            'required' => 0,
                            'conditional_logic' => 0,
                            'wrapper' => array (
                                'width' => '',
                                'class' => '',
                                'id' => '',
                            ),
                            'button_label' => 'Add Menu Item',
                            'min' => '',
                            'max' => '',
                            'layouts' => array (
                                array (
                                    'key' => '56532eee6ef81',
                                    'name' => 'menuItem',
                                    'label' => 'Menu Item',
                                    'display' => 'block',
                                    'sub_fields' => array (
                                        array (
                                            'key' => 'field_56532f0418f41',
                                            'label' => 'Label',
                                            'name' => 'menuITem__label',
                                            'type' => 'text',
                                            'instructions' => '',
                                            'required' => 0,
                                            'conditional_logic' => 0,
                                            'wrapper' => array (
                                                'width' => 50,
                                                'class' => '',
                                                'id' => '',
                                            ),
                                            'default_value' => '',
                                            'placeholder' => '',
                                            'prepend' => '',
                                            'append' => '',
                                            'maxlength' => '',
                                            'readonly' => 0,
                                            'disabled' => 0,
                                        ),
                                        array (
                                            'key' => 'field_565333d218f45',
                                            'label' => 'Class',
                                            'name' => 'menuItem__class',
                                            'type' => 'text',
                                            'instructions' => '',
                                            'required' => 0,
                                            'conditional_logic' => 0,
                                            'wrapper' => array (
                                                'width' => 50,
                                                'class' => '',
                                                'id' => '',
                                            ),
                                            'default_value' => '',
                                            'placeholder' => '',
                                            'prepend' => '',
                                            'append' => '',
                                            'maxlength' => '',
                                            'readonly' => 0,
                                            'disabled' => 0,
                                        ),
                                        array (
                                            'key' => 'field_565342ef11b29',
                                            'label' => 'Link Type',
                                            'name' => 'menuItem__type',
                                            'type' => 'radio',
                                            'instructions' => '',
                                            'required' => 0,
                                            'conditional_logic' => 0,
                                            'wrapper' => array (
                                                'width' => 25,
                                                'class' => '',
                                                'id' => '',
                                            ),
                                            'choices' => array (
                                                'page' => 'Page',
                                                'cat' => 'Category',
                                                'url' => 'URL',
                                                'cust' => 'Custom',
                                            ),
                                            'other_choice' => 0,
                                            'save_other_choice' => 0,
                                            'default_value' => '',
                                            'layout' => 'vertical',
                                        ),
                                        array (
                                            'key' => 'field_56532f2d18f42',
                                            'label' => 'Page',
                                            'name' => 'menuItem__page',
                                            'type' => 'page_link',
                                            'instructions' => '',
                                            'required' => 0,
                                            'conditional_logic' => array (
                                                array (
                                                    array (
                                                        'field' => 'field_565342ef11b29',
                                                        'operator' => '==',
                                                        'value' => 'page',
                                                    ),
                                                ),
                                            ),
                                            'wrapper' => array (
                                                'width' => 75,
                                                'class' => '',
                                                'id' => '',
                                            ),
                                            'post_type' => array (
                                            ),
                                            'taxonomy' => array (
                                            ),
                                            'allow_null' => 0,
                                            'multiple' => 0,
                                        ),
                                        array (
                                            'key' => 'field_5653434f11b2a',
                                            'label' => 'Category',
                                            'name' => 'menuItem__cat',
                                            'type' => 'taxonomy',
                                            'instructions' => '',
                                            'required' => 0,
                                            'conditional_logic' => array (
                                                array (
                                                    array (
                                                        'field' => 'field_565342ef11b29',
                                                        'operator' => '==',
                                                        'value' => 'cat',
                                                    ),
                                                ),
                                            ),
                                            'wrapper' => array (
                                                'width' => 75,
                                                'class' => '',
                                                'id' => '',
                                            ),
                                            'taxonomy' => 'category',
                                            'field_type' => 'select',
                                            'allow_null' => 0,
                                            'add_term' => 1,
                                            'save_terms' => 0,
                                            'load_terms' => 0,
                                            'return_format' => 'id',
                                            'multiple' => 0,
                                        ),
                                        array (
                                            'key' => 'field_5653439311b2c',
                                            'label' => 'Custom',
                                            'name' => 'menuItem__cstm',
                                            'type' => 'text',
                                            'instructions' => '',
                                            'required' => 0,
                                            'conditional_logic' => array (
                                                array (
                                                    array (
                                                        'field' => 'field_565342ef11b29',
                                                        'operator' => '==',
                                                        'value' => 'cust',
                                                    ),
                                                ),
                                            ),
                                            'wrapper' => array (
                                                'width' => 75,
                                                'class' => '',
                                                'id' => '',
                                            ),
                                            'default_value' => '',
                                            'placeholder' => '',
                                            'prepend' => '',
                                            'append' => '',
                                            'maxlength' => '',
                                            'readonly' => 0,
                                            'disabled' => 0,
                                        ),
                                        array (
                                            'key' => 'field_5653437011b2b',
                                            'label' => 'URL',
                                            'name' => 'menuItem__url',
                                            'type' => 'url',
                                            'instructions' => '',
                                            'required' => 0,
                                            'conditional_logic' => array (
                                                array (
                                                    array (
                                                        'field' => 'field_565342ef11b29',
                                                        'operator' => '==',
                                                        'value' => 'url',
                                                    ),
                                                ),
                                            ),
                                            'wrapper' => array (
                                                'width' => 75,
                                                'class' => '',
                                                'id' => '',
                                            ),
                                            'default_value' => '',
                                            'placeholder' => '',
                                        ),
                                    ),
                                    'min' => '',
                                    'max' => '',
                                ),
                            ),
                        ),
                    ),
                    'min' => '',
                    'max' => '',
                ),
            ),
        ),
    ),
    'location' => array (
        array (
            array (
                'param' => 'options_page',
                'operator' => '==',
                'value' => 'acf-options-theme-options',
            ),
        ),
    ),
    'menu_order' => 0,
    'position' => 'normal',
    'style' => 'default',
    'label_placement' => 'top',
    'instruction_placement' => 'label',
    'hide_on_screen' => '',
    'active' => 1,
    'description' => '',
));

endif;

UX

function acfMenu($name) {
    if( function_exists('get_field') ) :
        $getMenus = get_field('menus', 'option');
        foreach($getMenus as $menuData) : 
            if( $menuData['menu__name'] == $name ) : 
              // Do stuff to build your menu
            endif;
        endforeach;
    endif;
}

This is just a quick sample, but with the options that ACF offers, you could tack all kinds of stuff onto a menu item and then code out the UI at will.

In application to your specific question, one could in turn apply conditional selections to what type of link you're supplying (see attached image). ACF allows many different parameters such as page links, category links, or straight URLs. A conditional selection of these items would allow one to change the type of the menu item without erasing classes or other attributes.

  • Nice to see suggestions - I'm sure a screenshot would help understanding your idea better ;-) – birgire Nov 23 '15 at 16:24
  • I'm not sure I can get a screen shot that big. Nested ACF features can get kind of messy. – Tim Plummer Nov 23 '15 at 16:26
0

This may help define the right approach.

The dummy-down philosophy behind WP drives the way that they have setup menus in the first place, and is just one of the reasons why WP can be a poor choice as the framework for handling a site with large amounts of oft changing content.

In trying to make content management as dummy proof as possible it locks it into particular paradigms which often creates extra work, often for no good reason. You can't save menu templates, nor duplicate existing menus, nor safely store menu re-usable menu items without experiencing loss of config.

I like your suggestion which would be a good alternative to the native menu formats they provide, as it's a good middle ground between the dummy-proof approach while still offering a lot more flexiblity and speed of deployment. And I'd add a sort parameter as an alternative to the annoying drag and drop process which can create so much fiddling around.

However, while I would want the menus management in WP to be changed, pushing too far down this path is against the core WP philosophy and might mean that it is no longer catering to the lowest common denominator which is largely the reason for the popularity of WP.

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.